Qt QWidget/QPainter show()和#x2B;paintEvent()->;在旧位置显示矩形

Qt QWidget/QPainter show()和#x2B;paintEvent()->;在旧位置显示矩形,qt,transparent,qwidget,paintevent,Qt,Transparent,Qwidget,Paintevent,我必须在透明的Qt窗口上显示不同位置的矩形。 在显示窗口之前,我设置了新的矩形位置。有时,旧位置会显示几毫秒。(例如,m_y_pos=100而不是m_y_pos=400)。在显示窗口和更新窗口之间似乎存在某种竞争条件 我希望有人知道一个建议 谢谢纸浆 示例代码: #include <QApplication> #include <QtWidgets/QMainWindow> #include <QPaintEvent> #include <QTimer&

我必须在透明的Qt窗口上显示不同位置的矩形。 在显示窗口之前,我设置了新的矩形位置。有时,旧位置会显示几毫秒。(例如,m_y_pos=100而不是m_y_pos=400)。在显示窗口和更新窗口之间似乎存在某种竞争条件

我希望有人知道一个建议

谢谢纸浆

示例代码:

#include <QApplication>
#include <QtWidgets/QMainWindow>
#include <QPaintEvent>
#include <QTimer>
#include <QDebug>
#include <QPainter>

class QtGuiApplication : public QMainWindow
{
  Q_OBJECT

public:
  int m_x_pos;
  int m_y_pos;
  QTimer* m_timer;

  QtGuiApplication(QWidget *parent = Q_NULLPTR) : QMainWindow(parent), m_x_pos(100), m_y_pos(100)
  {
    setGeometry(100, 100, 1000, 1000);

    //Make Window transparent
    setAttribute(Qt::WA_NoSystemBackground, true);
    setAttribute(Qt::WA_TranslucentBackground);
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);

    m_timer = new QTimer(this);
    m_timer->setInterval(500);
    m_timer->start();
    connect(m_timer, &QTimer::timeout, this, &QtGuiApplication::Tick);
  }

  private slots:

  //toggle visibility of the window to show the effect
  void Tick()
  {
    if (isVisible())
    {
      hide();
    }
    else
    {
      //Set new position before showing the window
      m_y_pos = m_y_pos == 100 ? 400 : 100;
      show();
    }
  }

  //Paint rectangles at different positions
  void paintEvent(QPaintEvent* event)
  {
    QPainter painter(this);

    painter.setBrush(Qt::red);
    painter.setPen(Qt::black);

    for (int i = 0; i < event->rect().width(); i += 50)
    {
      painter.drawRect(m_x_pos + i, m_y_pos, 30, 30);
    }
  }

};

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  QtGuiApplication w;
  w.show();
  return a.exec();
}
#包括
#包括
#包括
#包括
#包括
#包括
类QTGUI应用程序:公共QMainWindow
{
Q_对象
公众:
int m_x_pos;
国际货币基金组织;
QTimer*m_定时器;
qtgui应用程序(QWidget*parent=Q_NULLPTR):QMainWindow(parent)、m_x_pos(100)、m_y_pos(100)
{
集合几何(10010010001000);
//使窗户透明
setAttribute(Qt::WA_NoSystemBackground,true);
setAttribute(Qt::WA_半透明背景);
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
m_timer=新的QTimer(此);
m_定时器->设置间隔(500);
m_定时器->启动();
连接(m_定时器,&QTimer::timeout,this,&QtGuiApplication::Tick);
}
专用插槽:
//切换窗口的可见性以显示效果
空勾()
{
if(isVisible())
{
隐藏();
}
其他的
{
//在显示窗口之前设置新位置
m_y_pos=m_y_pos==100?400:100;
show();
}
}
//在不同位置绘制矩形
无效paintEvent(QPaintEvent*事件)
{
油漆工(本);
画家。挫折(Qt::红色);
画师:设置笔(Qt::黑色);
对于(int i=0;irect().width();i+=50)
{
painter.drawRect(m_x_pos+i,m_y_pos,30,30);
}
}
};
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
qtguiw;
w、 show();
返回a.exec();
}

更改位置后,您缺少对
update()
的调用。通常,这应该被分解为
setPos
方法

一旦这样做,就不再需要
hide()
show()
:每次
setPos
调用都会根据需要更新小部件

您应该从满足您需求的最基本类派生:
QWidget
。毕竟,您没有使用
QMainWindow
的任何功能

// https://github.com/KubaO/stackoverflown/tree/master/questions/rect-paint-42194052
#include <QtWidgets>

class Window : public QWidget
{
   QPointF m_pos{100, 100};
   void paintEvent(QPaintEvent* event) override
   {
      QPainter painter(this);
      painter.setBrush(Qt::red);
      painter.setPen(Qt::black);
      for (int i = 0; i < event->rect().width(); i += 50)
         painter.drawRect(QRectF(m_pos.x() + i, m_pos.y(), 30, 30));
   }
public:
   Window(QWidget *parent = nullptr) : QWidget(parent)
   {
      setAttribute(Qt::WA_NoSystemBackground, true);
      setAttribute(Qt::WA_TranslucentBackground);
      setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint
                     | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
   }
   void setPos(const QPointF & pos) {
      m_pos = pos;
      update();
   }
};

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   Window w;
   QTimer timer;
   QObject::connect(&timer, &QTimer::timeout, [&w]{
      static bool toggle{};
      if (!w.isVisible()) {
         toggle = !toggle;
         if (toggle)
            w.setPos({200, 200});
         else
            w.setPos({100, 100});
      };
      w.setVisible(!w.isVisible());
   });
   timer.start(500);
   w.resize(1000, 500);
   return app.exec();
}
//https://github.com/KubaO/stackoverflown/tree/master/questions/rect-paint-42194052
#包括
类窗口:公共QWidget
{
QPointF m_pos{100,100};
无效paintEvent(QPaintEvent*事件)覆盖
{
油漆工(本);
画家。挫折(Qt::红色);
画师:设置笔(Qt::黑色);
对于(int i=0;irect().width();i+=50)
painter.drawRect(QRectF(m_pos.x()+i,m_pos.y(),30,30));
}
公众:
窗口(QWidget*parent=nullptr):QWidget(parent)
{
setAttribute(Qt::WA_NoSystemBackground,true);
setAttribute(Qt::WA_半透明背景);
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint)
|Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
}
无效设置位置(常量QPointF和位置){
m_pos=pos;
更新();
}
};
int main(int argc,字符**argv){
QApplication app{argc,argv};
窗口w;
定时器;
QObject::connect(&timer,&QTimer::timeout,[&w]{
静态布尔开关{};
如果(!w.isVisible()){
切换=!切换;
如果(切换)
w、 setPos({200200});
其他的
w、 setPos({100100});
};
w、 setVisible(!w.isVisible());
});
定时器启动(500);
w、 调整大小(1000500);
返回app.exec();
}

我无法在此处重现您的问题,但一般来说,只要参数改变了小部件的外观,您就应该通过调用
update()
通知喷漆系统您的小部件需要更新。(即,在您的情况下,直接在
Tick()
中设置
m_y_pos
后)行为只能在启用Aero的Windows 7下复制。感谢您的解决方案。我对它进行了测试:效果仍然存在(Windows 7,启用了Aero),因为如果窗口不可见,update()将无效。目前,我使用了一种变通方法:我移动屏幕的窗口,而不是隐藏它。(是的,很糟糕…)那就是Qt错误。