作业:搞个这个
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <QWidget>
#include <QPainter>
#include <QTimer>
#include <QTime>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void paintEvent(QPaintEvent *event);
private:
Ui::Widget *ui;
QTimer timer;
};
#endif // WIDGET_H
源代码
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timer.start(1000);
connect(&timer,&QTimer::timeout,[&](){
this->update();
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
//实例化一个画家
QPainter painter(this);
//设置字体
QFont font;
font.setPointSize(20);
font.setFamily("楷体");
//设置画笔
QPen pen;
pen.setColor(QColor(144,66,255));
pen.setStyle(Qt::SolidLine);
pen.setWidth(5);
painter.setPen(pen);
painter.setFont(font);
painter.translate(this->width()/2,this->height()/2);//重设画家坐标中心
painter.drawPoint(0,0);//画个圆心点
painter.setBrush(QBrush(Qt::lightGray)); // 设置填充颜色为浅灰色
painter.drawEllipse(QPoint(0,0),200,200);//画圆
//画小时刻度线
painter.setPen(QPen(Qt::black,5));
for (int i = 0; i < 12; ++i) {
painter.drawLine(198, 0, 190, 0);
painter.rotate(30.0); // 每次旋转30度
}
//画分钟刻度线
painter.setPen(QPen(Qt::black, 2));
for (int i = 0; i < 60; ++i) {
if (i % 5 != 0) { // 排除小时刻度线的位置
painter.drawLine(198, 0, 194, 0);
}
painter.rotate(6.0); // 每次旋转30度 // 每次旋转6度
}
QTime time=QTime::currentTime();
//画秒\分\时线
painter.setPen(QPen(Qt::blue,2)); //秒针长而细
painter.save();
double secondAngle= time.second()*6.0;
painter.rotate(secondAngle);
painter.drawLine(0,0,0,-150);
painter.restore();
painter.setPen(QPen(Qt::green,4)); //分针中等
painter.save();
double minuteAngle= (time.minute() + time.second() / 60.0) * 6.0;
painter.rotate(minuteAngle);
painter.drawLine(0,0,0,-100);
painter.restore();
painter.setPen(QPen(Qt::red,6)); //时针短而粗
painter.save();
double hourAngle= (time.hour() % 12 + time.minute() / 60.0) * 30.0;
painter.rotate(hourAngle);
painter.drawLine(0,0,0,-50);
painter.restore();
// 画1到12的数字
painter.setPen(QPen(Qt::black, 2)); // 设置数字的颜色
font.setPointSize(20); // 调整字体大小
painter.setFont(font);
for (int i = 1; i <= 12; i++) {
//
painter.rotate(30.0);
painter.drawText(-10,-170,QString::number(i));
}
}
思维导图:
面试题:
1、指针和引用的区别
指针定义时需要使用*号,引用定义时需要&;指针取值时需要用*运算符,引用使用时与目标使用方式一致;指针定义时需要给指针分配8byte空间,引用定义时不需要分配内存空间,与目标共享空间;指针初始化时,可以改变指针指向,引用初始化后不能更改引用目标;指针有二级指针,引用没有二级引用;指针有空指针,引用没空引用;指针进行偏移运算时是对地址的偏移,引用偏移时,是对目标值的偏移;指针不能指向右值,引用可以引用右值;指针定义是可以不初始化,引用初始化时必须初始化;指针可以有指针数组,引用不能定义引用数组等
2、C和C++的区别
C语言是完全面向过程的语言,C++是半面向对象半面向过程的语言;
C++是对C语言的补充,所有C语言的语法在C++都能使用;
C++的编译器是g++更加严格,C语言的编译器是gcc
C++文件的后缀为.cpp, .cxx .C .cc .hpp
3、对QT中哪些控件熟悉
QPushButton 按钮组件,可以设置按钮的位置、大小、文本内容,可以设置按钮的槽函数,从而作用到不同对象;QLabel 标签类组件,同样可以设置标签位置大小文本内容,还可以展示图片等;QLineEdit行编辑器,除了可以设置位置大小外,可以设置默认的文本内容,也可以设置文本密文,等
4、信号与槽机制
原理:一个组件用于发射信号,与之绑定的组件在收到信号后会立即做出相应反应
信号就是信号函数,定义在signals权限下,是一个不完整的函数,只有函数声明没有函数定义,不能当作普通函数一样被调用,只能被发射出去
槽就是槽函数,定义在类的slots权限下,是一个完整的函数,既有函数声明又有函数定义,返回值类型为void,槽函数可以当作普通函数一样被调用,但是普通函数不能当作槽函数接收信号
5、对象树模型
在对象树模型中,子组件构造时,需要指定父组件而存在;子组件的生命周期由父组件管理;当父组件展示时,会将子组将一并展示,当父组件释放空间时,会将加载在该组件上的所有子组件的空间一并释放;对象树模型能够保证各个组件的内存不被泄露;在栈区申请的组件,程序结束后其空间由系统自动回收,在堆区申请的组件,结束后由其父组件进行资源回收;父组件和子组件要用于共同的祖先类,实现的理论基础为多态;每一个组件都拥有一个父组件指针和子组件链表
1、什么情况下需要使用多线程
当程序需要同时执行多个任务时,可以使用多线程;多线程可以用于提高CPU利用率从而提高程序执行速度;可以充分利用cpu多核心;可以同时执行多个I/O操作等
2、使用多线程需要注意什么
多线程在访问临界资源时会出现抢占公共资源的现象,称之为竞态,导致线程中的数据出现错误;此时可以引入互斥锁来解决该问题,即产生一个特殊的临界资源,该临界资源在同一时刻只能被一个线程拥有,当一个线程试图去锁定被另一个线程锁定的互斥锁时,其会被阻塞,直到其被解锁;另外线程之间存在同步问题,就是多个线程任务有顺序的执行,由于多个任务有顺序的执行了,同一时刻对临界资源的访问只有一个线程了
3、poll、Epoll和Select的区别
select的监视数量有限,其上限为1024,当监视的描述符数量超过1024就会出问题;select监视列表无法扩容;select需要自己管理激活的套接字;select查询哪个套接字激活了是一个双重循环,效率低下;poll查询哪个套接字激活也是查询数组,效率依然底下;而epoll允许自动扩容;内核部分也是以二叉树储存所有描述符,因此查询描述符效率比前两者高。
4、智能指针有哪些,区别
有unique_ptr shared_ptr weak_ptr auto_ptr(已经弃用)
unique_ptr 表示对所指对象的独占所有权,同一时间智能有一个unique_ptr拥有某个对象;不支持拷贝构造和拷贝赋值,只能通过移动操作来转移所有权
shared_ptr允许多个智能指针共享同一对象,当最后一个shared_ptr被销毁时,对象才被释放;其内部维护一个用于计数的对象
weak_prt是弱引用,不会影响shared_ptr的引用计数,用于打破循环引用或者临时访问shared_ptr管理的对象
5、共享内存和消息队列的区别
消息队列本质上在内核空间维护了一个队列,发送者可以将消息先放入到该队列上,接收者根据自己的需求读取队列上的信息;消息队列的消息遵循先进先出原则,如果取出时不指定类型,则默认取第一个,如果指定了类型,则取第一个放入队列中的该消息;消息队列独立于进程而存在,当一个进程将消息放入队列后,及时进程退出了,也不会删除消息队列中的该消息;大小为16kb
共享内存本质上在独立于多个进程外,分配一个物理内存的映射,使得多个进程可以共享该内存空间;共享内存具有时效性,存放到共享内存区域中的数据,如果不及时读取,下一次写入后,前面的数据会被覆盖;共享内存的操作不是一次性的,写入到共享内存中的数据,即使读取出去后,依然存在于共享内存,直到下一次被覆盖