QPixmap on QLabel doesn't show correctly - c++

I am trying to draw some shape with QPainter class and save it to disk. As far as I know the easiest way is to use QPainter to draw into a QPixmap, visualize in the pixmap though a QLabel, and use QPixmap::save.
But when I run this test I see only a little black box inside the QWidget.
MyWidget::MyWidget()
{
std::cout << "MyWidget > ." << std::endl;
l = new QLabel();
l->setParent(this);
pixmap = new QPixmap(460, 480);
painter = new QPainter(pixmap);
}
MyWidget::~MyWidget()
{
delete pixmap;
delete painter;
}
void MyWidget::paintEvent(QPaintEvent *event)
{
std::cout << "dudee" << std::endl;
painter->begin(pixmap);
painter->drawLine(1,1,100,100);
QPen myPen(Qt::black, 2, Qt::SolidLine);
painter->setPen(myPen);
painter->drawLine(100,100,100,1);
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(QPen(Qt::black, 3, Qt::DashDotLine, Qt::RoundCap));
painter->setBrush(QBrush(Qt::green, Qt::SolidPattern));
painter->drawEllipse(200, 80, 400, 240);
painter->end();
l->setPixmap(*pixmap);
}
I have tried to add some l->update() but it doesn't change anything..
EDIT:
It should be an animation. I get the animation work through a QTimer that call every n msec the function for draw (not the paintEvent as the answer suggest)

You need instance of QPainter only during painting something. You don't need to keep it as class member.
Pixmap may be declared as class member, not as pointer.
Paint should be done once. It is bad idea to draw you external pixmap inside paintEvent, because you don't know, when exactly paintEvent will be called (and how much times).
You must not set pixmap for a label inside paint event, because call of l->setPixmap forces your widget to update => you will get infinite loop of draw->set->update->draw...
Solution:
Create somewhere a pixmap and paint on it necessary content.
Set content to a label, when it necessary (for example, after drawing).
Do not call update() - it will be called automatically, when you will set pixmap to label.
EDITED code:
Simple class for edited question:
AnimationSample.h
#ifndef ANIMATIONSAMPLE_H
#define ANIMATIONSAMPLE_H
#include <QWidget>
#include <QPixmap>
#include <QLabel>
#include <QPointer>
#include <QTimer>
class AnimationSample
: public QWidget
{
Q_OBJECT
public:
AnimationSample( QWidget *parent = NULL );
~AnimationSample();
private slots:
void onTick();
private:
QPointer< QLabel > m_label;
QPointer< QTimer > m_timer;
int m_salt;
};
#endif // ANIMATIONSAMPLE_H
AnimationSample.cpp
#include "AnimationSample.h"
#include <QPixmap>
#include <QPainter>
AnimationSample::AnimationSample( QWidget *parent )
: QWidget( parent )
, m_salt( 1 )
{
m_label = new QLabel( this );
m_label->setFixedSize( 100, 100 );
m_timer = new QTimer( this );
connect( m_timer, SIGNAL( timeout() ), SLOT( onTick() ) );
m_timer->start( 250 );
}
AnimationSample::~AnimationSample()
{
}
void AnimationSample::onTick()
{
QPixmap pic( 100, 100 );
QPainter p( &pic );
QPen myPen( Qt::black, 2, Qt::SolidLine );
p.setPen( myPen );
p.drawLine( 0, 0, m_salt, m_salt );
m_salt = (m_salt + 1) % 100;
m_label->setPixmap( pic );
}

Related

How to fix: custom QGraphicsItem receiving mousePressEvent coordinates late/laggy?

I have a "standard" Qt5 QWidgets application, with a MainWindow that includes a QGraphicsView in the mainwindow.ui created in QtCreator. That QGraphicsView has its scene set to a simple subclass of QGraphicsScene, which has a big rectangle in the background that is a subclass of QGraphicsRectItem which reimplements the mousePressEvent() and mouseReleaseEvent() handlers of the QGraphicsRectItem. Running on Ubuntu 18.04, which shouldn't matter, but just incase...
Everything is working, except... the 2nd and later times I press the left (or any) mouse button, the coordinates reported in the mousePressEvent's QGraphicsSceneMouseEvent buttonDownScenePos are "stale" - the same as the previous mouse click, not the new location where the mouse is when the new click happened. The mouseReleaseEvent reports coordinates as expected.
Is there any way to get the buttonDownScenePos of the mousePressEvent to stay current with the actual position of the mouse when clicked, instead of the previous mouse location?
I feel like I have dealt with a similar issue in the past which had something to do with double-click processing, that the event is reported before it knows if a double-click has happened or not. In this instance, double-click events are not important, but it would be nice to be able to respond to the single click as soon as it happens, instead of waiting for the release event.
Relevant code:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
class Board;
class BoardScene;
#include <QMainWindow>
#include <QPointer>
#include "board.h"
#include "boardscene.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{ Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void drawBoard();
private:
Ui::MainWindow *ui;
QPointer<Board> board;
QPointer<BoardScene> boardScene;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
board = new Board( this );
boardScene = new BoardScene( board, this );
ui->boardView->setScene( boardScene );
ui->boardView->setDragMode( QGraphicsView::ScrollHandDrag );
ui->boardView->scale( 40.0, 40.0 );
drawBoard();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::drawBoard()
{ }
boardscene.h
#ifndef BOARDSCENE_H
#define BOARDSCENE_H
class Board;
#include <QGraphicsScene>
#include "board.h"
#include "boardrect.h"
class BoardScene : public QGraphicsScene
{ Q_OBJECT
public:
BoardScene( Board *pbp, QObject *parent = nullptr );
void drawGrid();
Board *bp;
QBrush backBrush,blackBrush,whiteBrush;
QPen linePen;
};
#endif // BOARDSCENE_H
boardscene.cpp
#include "boardscene.h"
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
BoardScene::BoardScene( Board *pbp, QObject *parent ) : QGraphicsScene ( parent )
{ bp = pbp;
backBrush = QBrush( QColor( 224,152, 64 ) );
blackBrush = QBrush( QColor( 0, 0, 0 ) );
whiteBrush = QBrush( QColor( 255,255,255 ) );
linePen = QPen ( QColor( 0, 0, 0 ) );
linePen.setWidth( 0 );
drawGrid();
}
void BoardScene::drawGrid()
{ QGraphicsLineItem *lip;
BoardRect *rip;
setBackgroundBrush( blackBrush );
rip = new BoardRect( QRectF( -2.0, -2.0, (qreal)(bp->Xsize +3), (qreal)(bp->Ysize + 3) ), nullptr );
rip->setBrush( backBrush );
rip->setPen( linePen );
addItem( rip );
for ( int x = 0; x < bp->Xsize; x++ )
{ lip = addLine( QLineF( (qreal)x, 0.0, (qreal)x, (qreal)(bp->Ysize - 1) ), linePen );
lip->setAcceptedMouseButtons( Qt::NoButton );
}
for ( int y = 0; y < bp->Ysize; y++ )
{ lip = addLine( QLineF( 0.0, (qreal)y, (qreal)(bp->Xsize - 1), (qreal)y ), linePen );
lip->setAcceptedMouseButtons( Qt::NoButton );
}
}
boardrect.h
#ifndef BOARDRECT_H
#define BOARDRECT_H
#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>
class BoardRect : public QGraphicsRectItem
{
public:
BoardRect( const QRectF &rect, QGraphicsItem *parent = nullptr );
~BoardRect() {}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};
#endif // BOARDRECT_H
boardrect.cpp
#include "boardrect.h"
BoardRect::BoardRect( const QRectF &rect, QGraphicsItem *parent ) : QGraphicsRectItem( rect, parent )
{}
void BoardRect::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ QString msg = QString("press %1 %2").arg(event->buttonDownScenePos(event->button()).rx())
.arg(event->buttonDownScenePos(event->button()).ry());
qDebug( qPrintable( msg ) );
QGraphicsRectItem::mousePressEvent(event);
event->accept();
}
void BoardRect::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ QString msg = QString("release %1 %2").arg(event->buttonDownScenePos(event->button()).rx())
.arg(event->buttonDownScenePos(event->button()).ry());
qDebug( qPrintable( msg ) );
QGraphicsRectItem::mousePressEvent(event);
event->accept();
}
On the first click after running, the reported coordinates agree well with the location on the grid where the mouse was clicked, both for press and release - they both show where the button went down.
However, on the 2nd and later clicks, the mousePressEvent reports the same coordinates as the previous mousePress and Release events, while the mouseReleaseEvent reports the coordinates where the mouse button "went down" in the current event.
One final bit of weirdness: when clicking left, then right, then left again, the coordinate reported by mousePressEvent for the 2nd left click is the previous left click coordinate, skipping over the right click coordinate to go back to where the mouse button went down on the last left click.
Any ideas? Thanks.
I have an app using the same components: a qgraphicsview and a qgraphicsscene composed by some number of qgraphicsitems. It is a virtual MIDI piano keyboard just in case you want to take a look to the code. In my case, all the qgraphicsitems (the piano keys) have setAcceptedMouseButtons(Qt::NoButton), and the mouse events are handled at the scene level instead of the graphics item. I've never observed a problem like yours.
QGraphicsSceneMouseEvent::buttonDownPos(Qt::MouseButton button)
Returns the mouse cursor position in item coordinates where the
specified button was clicked.
It returns the coordinates from the graphics item you are clicking on (as the documentation says). Maybe you just click in the same spot?
If you want the scene position, just use mapToScene or QGraphicsSceneMouseEvent::buttonDownScenePos(Qt::MouseButton button) or event->scenePos().
PS.
and use QPointF::x() and QPointF::y() instead of rx() and ry(). You don't need a reference and manipulate the position.

How to draw with QPainter on a specific widget from a group of widgets in QMainWindow?

This is my code:
#include "mainwindow.h"
#include <QDebug>
#include <QCameraInfo>
#include <QHBoxLayout>
#include <fstream>
#include <assert.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_QPushButton_calibration = new QPushButton("Calibrate", this);
connect(m_QPushButton_calibration, SIGNAL (released()),this, SLOT (handleButton()));
QList<QCameraInfo> l_QListQCameraInfo_available_cameras = QCameraInfo::availableCameras();
m_QWidget_viewfinder_holder = new QWidget;
m_QWidget_viewfinder_holder->setStyleSheet ("background-color: black");
m_QCameraViewfinder_viewfinder = new QCameraViewfinder(m_QWidget_viewfinder_holder);
if (l_QListQCameraInfo_available_cameras.length() >= 2)
{
m_QCamera_required_camera = new QCamera (l_QListQCameraInfo_available_cameras[1]);
m_QCamera_required_camera->setViewfinder(m_QCameraViewfinder_viewfinder);
m_QCamera_required_camera->start ();
}
m_QWidget_central = new QWidget;
m_QGridLayout_central = new QGridLayout;
m_QWidget_central->setLayout (m_QGridLayout_central);
m_QGridLayout_central->addWidget (m_QPushButton_calibration, 0, 0, 1, 1);
m_QGridLayout_central->addWidget (m_QWidget_viewfinder_holder, 1, 0, 1, 1);
this->setCentralWidget (m_QWidget_central);
m_QCameraViewfinder_viewfinder->show();
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setPen(Qt::white);
painter.setFont(QFont("Arial", 30));
painter.drawText(rect(), Qt::AlignCenter, "Qt");
}
MainWindow::~MainWindow()
{
delete m_QPushButton_calibration;
delete m_QCameraViewfinder_viewfinder;
delete m_QCamera_required_camera;
delete m_QGridLayout_central;
delete m_QWidget_central;
}
void MainWindow::handleButton()
{
qDebug() << "handleButton";
}
I actually wish to draw a line on m_QWidget_viewfinder_holder widget.
How will that QPaintEvent function know where do I want it to draw line?
Can I use QPaintEvent as a member function in a class inherited from QMainWindow?
How to draw with QPainter on a specific widget from a group of widgets in QMainWindow?
You cannot draw on a widget from another widget. Each widget is responsible for drawing its own surface in the paintEvent() function.
How will that QPaintEvent function know where do I want it to draw line?
First, note that QPaintEvent is a class, not a function.
Now you probably want to talk about the paintEvent() function.
The function "knows" where to draw because it is part of a widget and the widget has a geometry.
For instance if I want to create a Rectangle widget that draws a rectangle with a 5px margin, I would write something like:
void Rectangle::paintEvent(QPaintEvent * e)
{
QRect rectangle(5, 5, width() - 5, height() - 5);
QPainter painter(this);
painter.drawRect(rectangle);
}
Can I use QPaintEvent as a member function in a class inherited from QMainWindow?
You can reimplement the paintEvent() member function in any class that inherits QWidget. If you inherits from a class that already draws something you need to call your parent class function.
void MainWindow::paintEvent(QPaintEvent *event)
{
QMainWindow::paintEvent(event); // Let QMainWindow draw itself
QPainter painter(this);
painter.setPen(Qt::white);
painter.setFont(QFont("Arial", 30));
painter.drawText(rect(), Qt::AlignCenter, "Qt");
}
However, please note that you are not likely willing to reimplement the painteEvent() of a MainWindow. What you generally want to do is to add a child widget to the MainWindow.
I actually wish to draw a line on m_QWidget_viewfinder_holder widget.
Create a ViewFinderHolder class like so:
class ViewFinderHolder: public QWidget {
Q_OBJECT
public:
explicit ViewFinder(QWidget *parent = 0)
...
}
Reimplement the paintEvent() function:
class ViewFinderHolder: public QWidget {
Q_OBJECT
public:
explicit ViewFinderHolder(QWidget *parent = 0)
...
protected:
void paintEvent(QPaintEvent *e);
}
void ViewFinderHolder::paintEvent(QPaintEvent *event)
{
QLineF line(10.0, 80.0, 90.0, 20.0);
QPainter(this);
painter.drawLine(line);
}
Finally in the MainWindow constructor replace:
m_QWidget_viewfinder_holder = new QWidget;
by:
m_QWidget_viewfinder_holder = new ViewFinder();
However, as m_QCameraViewfinder_viewfinder is a child of m_QWidget_viewfinder_holder, it will be drawn over it and may hide the drawing you did in ViewFinderHolder::paintEvent().
On a side note, you can remove the delete statements in the destructor of MainWindow. Deleting an instance of MainWidow will delete its child widgets.

Fading away widget in QT C++

I want to make a simple QWidget which is a simple rectangle fade away. The main problem is that the paint event paint at the same place every time in fact making the effect opposite, it make the colour stronger. Is there any way of achieving this functionality? Could you maybe provide some simple example?
My code:
`
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTimer>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
void paintEvent(QPaintEvent*);
~Widget();
private:
Ui::Widget *ui;
int alfa;
int i;
QTimer time;
};
#endif // WIDGET_H
`
and the cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QColor>
#include <QPainter>
#include <QBrush>
#include <QTimer>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent,Qt::Popup | Qt::FramelessWindowHint),
ui(new Ui::Widget),
time()
{
ui->setupUi(this);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_PaintOnScreen);
time.setInterval(500);
time.start();
connect(&time,SIGNAL(timeout()),this,SLOT(update()));
alfa=100;
i=0;
}
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
int rectBase = height();
QColor c(255,0,255);
alfa=alfa-(i*10);
c.setAlpha(alfa);
qDebug()<<c.alpha();
i++;
painter.setBrush(QBrush(c));
painter.drawRect(0, 0, width(),height());
}
Widget::~Widget()
{
delete ui;
}
You shouldn't rely on QWidget::paintEvent() to change your alpha level, since it can be called less or more than you want (multiple update() calls may result in only one paintEvent() and paintEvent() may be called when you don't expect it).
So a more reliable way to get to the result, is have a separate slot where you decrease the alpha level and then call update(). Your class definition might look like this:
class Widget : public QWidget
{
Q_OBJECT
public:
Widget( QWidget * inParent );
private:
void paintEvent(QPaintEvent *);
private slots:
void animate();
private:
QTimer * mTimer;
int mAlpha;
};
And the declaration:
Widget::Widget( QWidget * inParent )
:
QWidget( inParent ),
mTimer( new QTimer( this ) ),
mAlpha( 255 )
{
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_PaintOnScreen);
mTimer->setInterval( 40 );
mTimer->setSingleShot( false );
connect( mTimer, SIGNAL(timeout()), this, SLOT(animate()) );
mTimer->start();
}
void
Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setBrush( QColor(255,0,255,mAlpha ) );
painter.drawRect(rect());
}
void
Widget::animate()
{
if ( mAlpha > 0 )
{
mAlpha -= 3;
}
else
{
mTimer->stop();
}
update();
}
Notice that I did decrease the interval of the timer. You only called an update() every half a second. That typically does not result in a smooth animation.
I get a warning with this code on Kubuntu Linux, under Qt5:
QWidget::paintEngine: should no longer be called
The originating line is in qWarning("QWidget::paintEngine: Should no longer be called");, in src/widgets/kernel/qwidget_qpa.cpp and discussed a bit in this ticket:
https://qt.gitorious.org/qt/qtbase-harmattan/commit/3037525
You can get the warning to stop by removing the setAttribute(Qt::WA_PaintOnScreen);, so I did that. After taking that line out, it works for me--although your subtraction model is strange. You are modifying the alpha as well as changing the subtraction value on each iteration; you probably didn't intend both. So either change it to:
QColor c (255, 0, 255);
alfa = alfa - 10;
if (alfa >= 0) {
c.setAlpha(alfa);
} else {
time.stop();
}
...or:
QColor c(255,0,255);
if (alfa - i * 10 >= 0) {
c.setAlpha(alfa - i * 10);
i++;
} else {
time.stop();
}
Etc. (See also #PrisonMonkeys note on your timer not necessarily being the only source of update() calls.) Regarding getting these warnings to be more vocal so you don't miss them, you might look at The Essential Noisy Debug Hook For Qt, which I should update.
If with the change, an alpha blended window doesn't work on your platform at all, you should mention explicitly what your circumstance is...as it is working for me.

Editing frameless window in Qt

I've been created a frameless window in Qt that have widgets and background. but i have a problem in that form, when i resize form all widgets resize good but background not
See this pic for demonstration
When no resize occured:
http://0000.2.img98.net/out.php/i20624_no-resize.jpg
when resize occured:
http://0000.2.img98.net/out.php/i20625_with-resize.jpg
and here is my code for creating Form:
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QPushButton>
#include <QLabel>
#include <QComboBox>
#include <QPixmap>
#include <QVBoxLayout>
#include <QPainter>
#include <QMouseEvent>
#include <QtGui>
#include <QSizeGrip>
class MyWidget : public QWidget {
Q_OBJECT
private:
QPushButton* button;
QLabel* label;
QComboBox* combobox;
QPixmap pixmap;
public:
explicit MyWidget(QWidget *parent = 0) : QWidget(parent, Qt::FramelessWindowHint)
{
// Create some controls
button = new QPushButton();
label = new QLabel();
combobox = new QComboBox();
QVBoxLayout* l = new QVBoxLayout();
l->addWidget(button);
l->addWidget(label);
l->addWidget(combobox);
QSizeGrip *grip = new QSizeGrip(parent);
l->addWidget(grip, 0, Qt::AlignBottom | Qt::AlignRight);
setLayout(l);
resize (400, 500);
setAttribute(Qt::WA_TranslucentBackground); // enable translucent background
pixmap = QPixmap("./1.png");
}
protected:
virtual void paintEvent (QPaintEvent* event) {
QPainter painter(this);
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(0, 0, 0, 0));
QRect rec = pixmap.rect();
painter.drawRect(this->rect());
painter.drawPixmap(this->rect(), pixmap, rec);
}
private:
bool pressed;
QPoint mousePressPoint;
protected:
virtual void mousePressEvent ( QMouseEvent * event ) {
QWidget::mousePressEvent(event);
if (!pressed) {
pressed = true;
mousePressPoint = event->pos();
}
}
#endif // MYWIDGET_H
Since your controls are centered in the window but don't look like they are, it might indicate that there is a transparent border around the non-transparent part of the image you are using as background.
You can remove the transparency from the brush in paintEvent to confirm that, with, for example:
painter.setBrush(QColor(0, 0, 0, 255));
To be more clear, the problem is not in your code, but in the image: open the image with an editor, select only the non-transparent part, keep only that part by using the "cropping tool", and finally save the image.

draw in a QFrame on clicking a button.

Say there is a QPushButton named "Draw", a QLineEdit and a QFrame. On clicking the button I want to take a number from QLineEdit and draw a circle in a QFrame. How can I do this? Please provide me with the code.
P.S. The problem is that draw methods of the QPainter should be called in drawEvent method.
If #Kaleb Pederson's answer is not enough for you then here's a complete solution for a simple set-up matching what you describe. Tested with Qt 4.5.2 on Linux. I had some spare time... ;)
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 );
}
}
If you want your frame to do the drawing, then it needs a way to know that it should draw something, so create a slot that will receive notification:
/* 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));
}
Then, your frame subclass you need to override paintEvent() to draw the circle:
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());
}
}
As long as the slot responding to the button's clicked() signal emits a signal that calls the drawCircle slot with the correct arguments everything should work correctly.
You don't draw diectly onto a frame.
Start here graphicsview, it looks complicated at first - but GUI program is a big leap when you first encounter it
In most GUIs (Qt, OpenGL etc) you build up a list of elements you want to draw in your program and store them somehow - then there is a draw() function that gets called when the computer needs to draw your picture - eg when it is moved or another window is moved in front of it. The OnDraw or OnRepaint etc function then gets called and you have to draw the list of objects.
Another way to do this is to draw them all to an image (QOimage or QPixmap) and copy that to the screen in OnDraw or OnRepaint - you might do this for a graphics package for example.