【发布时间】:2023-03-06 05:24:01
【问题描述】:
假设有一个名为“Draw”的 QPushButton、一个 QLineEdit 和一个 QFrame。单击按钮时,我想从 QLineEdit 中获取一个数字并在 QFrame 中绘制一个圆圈。我怎样才能做到这一点?请把代码提供给我。
附:问题是QPainter的draw方法应该在drawEvent方法中调用。
【问题讨论】:
假设有一个名为“Draw”的 QPushButton、一个 QLineEdit 和一个 QFrame。单击按钮时,我想从 QLineEdit 中获取一个数字并在 QFrame 中绘制一个圆圈。我怎样才能做到这一点?请把代码提供给我。
附:问题是QPainter的draw方法应该在drawEvent方法中调用。
【问题讨论】:
如果@Kaleb Pederson's answer 对您来说还不够,那么这里有一个完整的解决方案,用于与您描述的内容相匹配的简单设置。在 Linux 上使用 Qt 4.5.2 进行测试。我有一些空闲时间... ;)
main.cpp:
#include <QApplication>
#include "window.h"
int main( int argc, char** argv )
{
QApplication qapp( argc, argv );
Window w;
w.show();
return qapp.exec();
}
window.h
#pragma once
class QLineEdit;
class QPushButton;
#include <QWidget>
class Frame;
class Window : public QWidget
{
Q_OBJECT
public:
Window();
private slots:
void onButtonClicked();
private:
QLineEdit* m_lineEdit;
QPushButton* m_pushButton;
Frame* m_frame;
};
window.cpp:
#include <QHBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include "frame.h"
#include "window.h"
Window::Window()
: m_lineEdit ( new QLineEdit( this ) )
, m_pushButton( new QPushButton( tr( "Draw" ), this ) )
, m_frame ( new Frame( this ) )
{
connect( m_pushButton, SIGNAL( clicked() )
, SLOT( onButtonClicked() ) );
QHBoxLayout*const hLayout = new QHBoxLayout;
hLayout->addWidget( m_lineEdit );
hLayout->addWidget( m_pushButton );
QVBoxLayout*const vLayout = new QVBoxLayout( this );
vLayout->addLayout( hLayout );
m_frame->setFixedSize( 300, 400 );
vLayout->addWidget( m_frame );
setLayout( vLayout );
}
void Window::onButtonClicked()
{
const int r = m_lineEdit->text().toInt(); // r == 0 if invalid
m_frame->setCircleRadius( r );
m_frame->update();
}
frame.h:
#pragma once
#include <QFrame>
class Frame : public QFrame
{
Q_OBJECT
public:
Frame( QWidget* );
void setCircleRadius( int );
protected:
void paintEvent( QPaintEvent* );
private:
int m_radius;
};
frame.cpp:
#include <QPainter>
#include "frame.h"
Frame::Frame( QWidget* parent )
: QFrame( parent )
, m_radius( 0 )
{
setFrameStyle( QFrame::Box );
}
void Frame::setCircleRadius( int radius )
{
m_radius = radius;
}
void Frame::paintEvent( QPaintEvent* pe )
{
QFrame::paintEvent( pe );
if ( m_radius > 0 )
{
QPainter p( this );
p.drawEllipse( rect().center(), m_radius, m_radius );
}
}
【讨论】:
如果你想让你的框架进行绘图,那么它需要一种方法来知道它应该绘制一些东西,所以创建一个接收通知的槽:
/* slot */ void drawCircle(QPoint origin, int radius) {
addCircle(origin, radius);
update(); // update the UI
}
void addCircle(QPoint origin, int radius) {
circleList.add(new Circle(origin,radius));
}
然后,您需要覆盖 paintEvent() 来绘制圆圈的框架子类:
void paintEvent(QPaintEvent *event) {
QFrame::paintEvent(event);
QPainter painter(this);
foreach (Circle c, circleList) { // understand foreach requirements
painter.drawEllipse(c.origin(), c.radius(), c.radius());
}
}
只要响应按钮的clicked() 信号的槽发出一个信号,用正确的参数调用drawCircle 槽,一切都应该正常工作。
【讨论】:
您不会直接在框架上绘图。
从这里开始graphicsview,一开始看起来很复杂——但是当你第一次遇到它时,GUI程序是一个很大的飞跃
在大多数 GUI(Qt、OpenGL 等)中,您会建立一个您想要在程序中绘制的元素列表并以某种方式存储它们 - 然后当计算机需要绘制您的图片时会调用一个 draw() 函数- 例如,当它被移动或另一个窗口移动到它前面时。然后调用 OnDraw 或 OnRepaint 等函数,您必须绘制对象列表。
另一种方法是将它们全部绘制到图像(QOimage 或 QPixmap)并在 OnDraw 或 OnRepaint 中将其复制到屏幕 - 例如,您可以为图形包执行此操作。
【讨论】:
QFrame 或其任何子类上绘图。有关工作示例,请参阅 my anwser。
QGraphicsView 存在之前就已经编写好了,我们从不费心移植到它,因为一切都很好。 QGraphicsView 是 GUI 的一个不错的新部分,但我不会说它是强制性的。