QT如何实现不点击鼠标就能触发 mouseMoveEvent(QMouseEvent *e):setMouseTracking(true)
QTableView如何实现单击事件:不需要重写单击事件,而是有clicked(QModelIndex),doubleClicked(QModelIndex)等信号
QGraphicsObject如何接收点击信号等:
1 bool GoodItem::sceneEvent(QEvent *event) 2 { 3 if(event->type() == QEvent::GraphicsSceneMousePress) 4 { 5 mousePressEvent((QGraphicsSceneMouseEvent *)event); 6 } 7 else if(event->type() == QEvent::GraphicsSceneMouseRelease) 8 { 9 mouseReleaseEvent((QGraphicsSceneMouseEvent *)event); 10 } 11 else if(event->type() == QEvent::GraphicsSceneMouseMove) 12 { 13 mouseMoveEvent((QGraphicsSceneMouseEvent *)event); 14 } 15 else if(event->type() == QEvent::GraphicsSceneMouseDoubleClick) 16 { 17 mouseDoubleClickEvent((QGraphicsSceneMouseEvent *)event); 18 } 19 return QGraphicsObject::sceneEvent(event); 20 }
QGraphicsItem如何触发重绘:该类存在update函数,注意是函数不是槽。
QT中tcp连接传递一个消息时,另一端完全可能把分成多个消息。
abort可以立即中断一个TCP连接的一端,此时该端既不能发送数据也不能接收数据。如果有数据正在传输中,可能会出问题。
disconnectFromHost可以在传输结束之后中断TCP连接的一端,此时该端既不能发送数据也不能接收数据。
使用同一个tcp连接在几乎同时传输两个字符串,那这两个字符串会不会混合到一起或者连起来,这真是个让人头痛的问题,谁知道求评论告知。通过定时器设置同时两个短字符串发现没有该情况,所以认为多次使用write函数发送字符串不会混合到一起,一次使用write函数发送过长字符串会分成多个。很不幸,最终发现多次发送的会混合到一起,看来以后要少用特例了呀。
new从堆中申请内存,直接申明则是从栈中申请内存,即申明的变量的生存期是在离它最近的{}之间,new出来的对象直到delete或者进程结束才会释放。
1 Widget::Widget(QWidget *parent) 2 : QWidget(parent) 3 { 4 timer = new QTimer(); 5 timer2 = new QTimer(); 6 timer->setSingleShot(true); 7 timer2->setSingleShot(true); 8 timer->start(1000); 9 timer2->start(1200); 10 connect(timer, SIGNAL(timeout()), this, SLOT(slot1())); 11 connect(timer, SIGNAL(timeout()), this, SLOT(slot2())); 12 connect(timer2, SIGNAL(timeout()), this, SLOT(slot1())); 13 } 14 15 void Widget::slot1() 16 { 17 cout << 1 << endl; 18 qint64 i=1e9; 19 while(i--); 20 } 21 22 void Widget::slot2() 23 { 24 cout << 2 << endl; 25 //while(1); 26 }
这样也能在输出1之后一会儿在输出2,1,那我觉得应该我的理解没问题,qt单线程中始终是一个个函数执行的,我不知道会不会同时发送多个信号,这也不重要,但是一定同时只会执行一个函数,而且在一个函数执行过程中其他函数会排队等待执行。
如果有谁能说明我的理解有错或者找到权威的说明,求科普
1 Widget::Widget(QWidget *parent) 2 : QWidget(parent) 3 { 4 timer = new QTimer(); 5 timer2 = new QTimer(); 6 timer->setSingleShot(true); 7 timer2->setSingleShot(true); 8 timer->start(1000); 9 timer2->start(1200); 10 connect(timer, SIGNAL(timeout()), this, SLOT(slot1())); 11 connect(timer, SIGNAL(timeout()), this, SLOT(slot2())); 12 connect(timer2, SIGNAL(timeout()), this, SLOT(slot1())); 13 connect(this, SIGNAL(signal1()), this, SLOT(slot1())); 14 count = 0; 15 } 16 17 void Widget::slot1() 18 { 19 cout << 1 << endl; 20 qint64 i=1e9; 21 while(i--); 22 count++; 23 if(count!=10) 24 emit signal1(); 25 } 26 27 void Widget::slot2() 28 { 29 cout << 2 << endl; 30 //while(1); 31 }
上面这段代码会先输出10个1,然后再输出1个2,然后再继续输出1,那我觉得应该是当前程序中没有函数在执行的时候有函数要求执行的时候立即执行,否则把要求执行的函数放入队列,当当前函数执行完之后才去执行队列中的下一个函数,当前函数执行完包括把该函数执行完而且如果该函数发送了信号且该信号对应了槽函数,那么等价于该函数在发送信号的位置直接调用了对应的槽函数。
1 #include "widget.h" 2 #include <stdio.h> 3 using namespace std; 4 5 Widget::Widget(QWidget *parent) 6 : QWidget(parent) 7 { 8 timer = new QTimer(); 9 timer2 = new QTimer(); 10 timer->setSingleShot(true); 11 timer2->setSingleShot(true); 12 timer->start(1000); 13 timer2->start(1200); 14 connect(timer, SIGNAL(timeout()), this, SLOT(slot1())); 15 connect(timer, SIGNAL(timeout()), this, SLOT(slot2())); 16 connect(timer2, SIGNAL(timeout()), this, SLOT(slot1())); 17 connect(this, SIGNAL(signal1()), this, SLOT(slot1())); 18 count = 0; 19 } 20 21 void Widget::slot1() 22 { 23 cout << 1 << endl; 24 qint64 i=1e9; 25 while(i--); 26 count++; 27 if(count!=3) 28 { 29 emit signal1(); 30 cout << 3 << endl; 31 } 32 } 33 34 void Widget::slot2() 35 { 36 cout << 2 << endl; 37 //while(1); 38 } 39 40 Widget::~Widget() 41 { 42 43 }
上面这段代码的执行结果是
1
1
1
3
3
2
1
1
1
1。。。。。。。。
感觉可以佐证我的观点。
1 #include "widget.h" 2 #include "form.h" 3 #include <stdio.h> 4 using namespace std; 5 6 Widget::Widget(QWidget *parent) 7 : QWidget(parent) 8 { 9 timer = new QTimer(); 10 timer->singleShot(10, this, SLOT(slot1())); 11 timer2 = new QTimer(); 12 timer2->start(100000); 13 timer3 = new QTimer(); 14 timer3->start(1000); 15 count=0; 16 connect(timer3, SIGNAL(timeout()), this, SLOT(slot2())); 17 } 18 19 void Widget::slot1() 20 { 21 qint64 i=1e10; 22 while(i--); 23 cout << 1 << endl; 24 cout << timer2->remainingTime() << endl; 25 } 26 27 void Widget::slot2() 28 { 29 cout << count++ << endl; 30 } 31 32 Widget::~Widget() 33 { 34 35 }
刚刚继续进行测试的代码,发现定时器事件发送信号连接槽的时候如果正在阻塞中好像直接就没了。。。。由此可以认为,定时器并没有单独开一个线程,程序阻塞的时候定时器也被阻塞住了,不能发送出timeout信号,但是获取remainingtime的值并不会发生错误,可以认为这个值在定时器中是直接根据时间计算出来的。
最后总结一下这个问题,正常情况下(比如connect的方式要正常),单线程程序不会同时执行两个函数,他会把函数排成队列,排的方式应该正常来说是很合理的。然后定时器在理论上会发送timeout信号的时候如果当前有函数在执行就不发送了,获取remainingtime函数一般不会有误差,可以认为这个是根据时间的计算得来的。感觉应该是当前有函数还在执行的时候是不能通过事件,定时器等等方式来触发别的函数的。
以上纯属个人根据普通的眼力和普通的电脑的观测结果来yy的,如果发现结论错误千万别奇怪顺便恳请留言告诉我一声。
顺便吐槽一下cout的缓存机制,厉害了,我的傻儿子。
QDataStream应该不存在C++中类的对齐问题,要方便不少,这样比如用到tcp协议传输数据的时候比较方便。
QByteArray outBlock;outBlock的地址和outBlock[0]的地址不一样。如果想用c++的read函数往outBlock中写入数据,那么应该用read(fd,outBlock.begin(),size)的形式,而且首先要执行outBlock.resize()来给outBlock分配内存。
QGraphicsTextItem的虚函数painter不能重写,否则他就不能按照原来的方式显示文字。