Qt初学者QPainter和QRect

Qt初学者QPainter和QRect,qt,qpainter,qrect,Qt,Qpainter,Qrect,我怎么画一个矩形呢 我试过两种不同的方法 void MyWidget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::black); QRect rect = QRect(290, 20, 70, 40); painter.drawText(rect, Qt::Alig

我怎么画一个矩形呢

我试过两种不同的方法

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}
这很好(即使参数既没有命名也没有使用),但我不想使用QPaintEvent*我对它没有任何用处

所以我试着重新命名我的函数

void MyWidget::draw()
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}
这不会显示任何内容(但没有错误)


如果我不使用QPaintEvent*?

包含最好的Qt教程,开始教程74对您很有用(Qpainter和QPen),教程75是如何使用QRect绘制矩形。

您的
paintEvent()
需要的任何数据都应该可以作为包含类的字段访问,在您的情况下,
MyWidget
的私有字段。这些私有字段可以通过“setters”向
MyWidget
的客户机公开,setters将在调用
MyWidget
上的
update()
之前设置数据值,这将触发调用
paintEvent()

当需要重新绘制小部件时,绘制事件是绘制系统调用的方法。这就是为什么简单地命名自己的方法不起作用的原因。油漆系统从不调用它

您确实应该使用
QPaintEvent
。它为您提供了需要绘制的矩形。此rect将基于小部件的大小,因此,不要在绘制事件中使用显式rect,而是将小部件设置为正确的大小。如果您的小部件移动、调整大小等,将生成一个绘制事件

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}
现在,如果您想将绘制逻辑分离到另一个方法中,这很好。但您需要在绘画活动中调用它:

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    draw(rect);
}

void MyWidget::draw(QRect &rect)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}
如果您想完全绕过绘制事件(如您所说),并且只想创建一个要显示的静态矩形,一种方法是只将其绘制一次到pixmap并在QLabel中显示:

QPixMap pix(200,100);
QPainter painter(&pix);
// do paint operations
painter.end()
someLabel.setPixmap(pix)
重写小部件的paintEvent()函数使您能够自定义小部件,并定期调用此函数以重新绘制小部件。因此,应在此功能中绘制任何图纸。但是,重写paintEvent()可能会导致一些性能问题。我更喜欢使用qgraphicscene和QGraphicsView,然后我会在场景中添加一个矩形,这是进行此类绘图的常用方法。请检查GraphicsView框架


还有@Mat告诉过你:“活动”是启动油漆工的正确方式。
QPainter只能在QPaintEvent事件后调用,该事件携带可以绘制对象的安全区域

因此,您必须找到另一种策略来传输数据,以提供帮助 我将提出一个简单的方法,可以调整到许多情况

widget.cpp

#包括
#包括“widget.h”
#定义最小DCX(0.1)
#定义最大DCX(5.0)
小部件::小部件(QWidget*父部件)
:QWidget(父项)
{    
dcx=MIN\u dcx;
设置固定大小(170100);
}
void小部件::paintEvent(QPaintEvent*事件)
{
Q_未使用(事件);
油漆工;
画家。开始(这个);
painter.setRenderInt(QPainter::抗锯齿);
画师:设置笔(Qt::黑色);
pcx=dcx*2;
QRect rect=QRect(50 dcx,25 dcx,60+pcx,40+pcx);
painter.drawText(rect,Qt::AlignCenter,printData);
画家。drawRect(rect);
结束();
}
void小部件::setPrintData(QString值){
打印数据=值;
dcx=(dcx>MAX\u dcx)?MIN\u dcx:dcx+MIN\u dcx;
}
widget.h

#ifndef小部件
#定义小部件
#包括
类Widget:publicqwidget
{
Q_对象
公众:
小部件(QWidget*父部件);
void setPrintData(QString值);
受保护的:
无效油漆事件(QPaintEvent*事件);
私人:
QString打印数据;
浮动dcx;
浮动pcx;
};
#恩迪夫
window.cpp

#包括
#包括“widget.h”
#包括“window.h”
#定义最大SDCX 20
Window::Window()
:QWidget()
{
gobject=新窗口小部件(此);
textMode=1;
rectMode=1;
gobject->setPrintData(msgs[textMode]);
QGridLayout*layout=新的QGridLayout;
布局->添加小部件(gobject,0,0);
设置布局(布局);
QTimer*定时器=新的QTimer(此);
连接(计时器、信号(timeout())、此、插槽(dataOnAir());
定时器->启动(10);
setWindowTitle(tr(“矩形抖动”);
}
void Window::dataOnAir(){
如果(++rectMode)>MAX_SDCX){
rectMode=0;
textMode^=1;
}
gobject->setPrintData(msgs[textMode]);
gobject->repaint();
}
window.h

\ifndef窗口
#定义窗口
#包括
#包括“widget.h”
类窗口:公共QWidget
{
Q_对象
公众:
窗口();
专用插槽:
void dataOnAir();
私人:
Widget*gobject;
const QString msgs[2]={“你好”,“世界”};
int-textMode;
int模式;
};
#恩迪夫
main.cpp

#包括
#包括“window.h”
int main(int argc,char*argv[])
{
QApplication应用程序(argc、argv);
窗口窗口;
window.show();
返回app.exec();
}
正如您在代码中看到的,在对象“widget”之外执行一个计时器

每10毫秒发送一次重绘,小部件重新绘制一个不同大小的“rect”,每20个周期(200毫秒)将文本“hello”更改为“world”

在本例中,您可以看到需要以任何方式覆盖QPainterDevice体系结构


您还可能会注意到“paintEvent”中的“event”被静音,并且没有直接使用,但执行序列Qpaint是必不可少的。

为什么您希望调用随机命名的函数来执行任何操作?你的第一种方法很好。没有命名参数(不需要)是合法的和惯用的C++。好,如果没有参数,第一个方法是否可以工作,但其余的都是一样的吗?不,不管你用与否,都需要这个参数。我不明白你为什么要删除它——忽略它不会让你付出任何代价。它会在我以后的工作中给我带来问题
#include <QtGui>
#include "widget.h"

#define MIN_DCX    (0.1)
#define MAX_DCX    (5.0)

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{    
    dcx=MIN_DCX;
    setFixedSize(170, 100);
}

void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event); 
    QPainter painter;
    painter.begin(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    pcx=dcx*2;
    QRect rect = QRect(50-dcx,25-dcx,60+pcx,40+pcx);
    painter.drawText(rect, Qt::AlignCenter,printData);
    painter.drawRect(rect);
    painter.end();

}

void Widget::setPrintData(QString value){
   printData = value;
   dcx=(dcx>MAX_DCX)?MIN_DCX:dcx+MIN_DCX;
}
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent);
    void setPrintData(QString value);

protected:
    void paintEvent(QPaintEvent *event);

private:
    QString printData;
    float dcx;
    float pcx;
};


#endif
#include <QtGui>
#include "widget.h"
#include "window.h"

#define MAX_SDCX  20

Window::Window()
    : QWidget()
{
    gobject = new Widget(this);

    textMode=1;
    rectMode=1;
    gobject->setPrintData(msgs[textMode]);

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(gobject, 0, 0);
    setLayout(layout);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(dataOnAir()));
    timer->start(10);

    setWindowTitle(tr("Rect Shaking"));
}



void Window::dataOnAir(){
    if((++rectMode)>MAX_SDCX){
        rectMode=0;
        textMode^=1;
    }
    gobject->setPrintData(msgs[textMode]);
    gobject->repaint();
}
#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>
#include "widget.h"

class Window : public QWidget
{
    Q_OBJECT

public:
    Window();

private slots:
    void dataOnAir();

private:
    Widget *gobject;
    const QString msgs[2] = {"Hello","World"};
    int textMode;
    int rectMode;
};

#endif
#include <QApplication>
#include "window.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Window window;
    window.show();
    return app.exec();
}