Qt Create a scene with a grid of individual rectangles - c++

I want to create a grid of 22x22 individual rectangles. I will be filling each rectangle with a colour based on a predefined colour scale.
At the moment my header file looks like this:
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QtGui>
#include <QtCore>
#include <QGraphicsScene>
#define GRIDDIM 22
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
QGraphicsScene *scene;
QGraphicsRectItem *rec[GRIDDIM*GRIDDIM];
protected:
void paintEvent(QPaintEvent *e);
};
#endif // DIALOG_H
So I have declared 22x22 individual rectangle objects in the rec[] array.
My .cpp file looks like this:
#include "dialog.h"
#include "ui_dialog.h"
#include <QGraphicsView>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
//rec = new QGraphicsRectItem;
ui->graphicsView->setScene(scene);
QBrush redBrush(Qt::red);
QBrush blueBrush(Qt::blue);
QPen blackPen(Qt::black);
QPen bluePen(Qt::blue);
blackPen.setWidth(0);
bluePen.setWidth(0);
int height = 15;
int width = 15;
int xpos = 0;
int ypos = 0;
for (int i=0;i<GRIDDIM;i++){
for(int j=0;j<GRIDDIM;j++){
scene->addRect(i*(width),j*(height),width,height,blackPen);
}
}
But this is just assigning the generic rect object by using addrect.
Is it possible to implement my rec[] array into the scene so that I can then say for example set rec[10] blue?
Using:
QGraphicsRectItem *rec = new QGraphicsRectItem(QRect(xpos,ypos,width,height));
Gives back an error:
allocation of incomplete type 'QGraphicsRectItem'
forward declaration of 'QGraphicsRectItem'

Related

Layout mismanagement issue in Qt Application

I have an application which shows some images in a grid and rest of the widgets in their respective positions. Something like this
Drawing inspiration from this i managed to solve keeping the aspect ratio of an image while resizing.
What are the issues:
The QLabel widgets(image widgets) overlap if QMainWindow is shrinked. Check the image below
The whole application is apparently not suited for different screens. Running this application on a laptop, layout is completely messed up.
What have i done:
Here is the MVCE code i have created
//ImageWidget.h
#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H
#include <QLabel>
#include <QResizeEvent>
#include <QWidget>
class ImageWidget : public QLabel
{
Q_OBJECT
public:
explicit ImageWidget(QWidget* parent = nullptr);
virtual QSize sizeHint() const;
QPixmap scaledPixmap() const;
virtual int widthForHeight(int height) const;
public slots:
void setPixmap ( const QPixmap& p);
void resizeEvent(QResizeEvent* ev);
private:
QPixmap pix;
};
#endif // IMAGEWIDGET_H
ImageWidget.cpp
#include "imagewidget.h"
ImageWidget::ImageWidget(QWidget* parent) :
QLabel(parent)
{
setStyleSheet("QLabel{margin-left: 10px; border-radius: 25px; background: white; color: #4A0C46;}");
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy.setWidthForHeight(true);
setSizePolicy(sizePolicy);
setMinimumSize(sizeHint());
}
void ImageWidget::setPixmap (const QPixmap& p)
{
pix = p;
QLabel::setPixmap(scaledPixmap());
}
/* virtual */ int ImageWidget::widthForHeight(int height) const
{
return pix.isNull() ? height * pix.height() / pix.width() : height;
}
QSize ImageWidget::sizeHint() const
{
if(pix.width() != 0)
{
int h = this->height();
return QSize(widthForHeight(h), h);
}
else
{
return QSize(300, 300);
}
}
QPixmap ImageWidget::scaledPixmap() const
{
auto scaled = pix.scaled(this->size() * devicePixelRatioF(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
scaled.setDevicePixelRatio(devicePixelRatioF());
return scaled;
}
void ImageWidget::resizeEvent(QResizeEvent* )
{
if (!pix.isNull())
{
QLabel::setPixmap(scaledPixmap());
}
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QTableWidget>
#include "imagewidget.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
virtual void resizeEvent(QResizeEvent* event) override;
private:
Ui::MainWindow *ui;
ImageWidget* lbl1;
ImageWidget* lbl2;
ImageWidget* lbl3;
ImageWidget* lbl4;
QPushButton* btn1;
QPushButton* btn2;
QPushButton* btn3;
QPushButton* btn4;
QTableWidget* tableWidget;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVBoxLayout>
#include <QTabWidget>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QTabBar>
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVBoxLayout* mainLayout = new QVBoxLayout;
QVBoxLayout* tabLay = new QVBoxLayout;
QHBoxLayout* buttonLay = new QHBoxLayout;
QGridLayout* gridLay = new QGridLayout;
QHBoxLayout* dockLay = new QHBoxLayout;
btn1 = new QPushButton(this);
btn1->setText("Button1");
btn2 = new QPushButton(this);
btn2->setText("Button2");
btn3 = new QPushButton(this);
btn3->setText("Button3");
btn4 = new QPushButton(this);
btn4->setText("Button4");
QTabWidget* tabView = new QTabWidget(this);
tabView->addTab(new QWidget(), "Table");
tabView->setMinimumSize(500, 300);
tabView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
tableWidget = new QTableWidget(this);
tableWidget->setFixedHeight(200);
lbl1 = new ImageWidget(this);
lbl2 = new ImageWidget(this);
lbl3 = new ImageWidget(this);
lbl4 = new ImageWidget(this);
QPixmap lbl1Pix("1.png");
QPixmap lbl2Pix("2.png");
QPixmap lbl3Pix("3.png");
QPixmap lbl4Pix("4.png");
lbl1->setPixmap(lbl1Pix);
lbl1->show();
lbl2->setPixmap(lbl2Pix);
lbl2->show();
lbl3->setPixmap(lbl3Pix);
lbl3->show();
lbl4->setPixmap(lbl4Pix);
lbl4->show();
buttonLay->addWidget(btn1);
buttonLay->addWidget(btn2);
buttonLay->addWidget(btn3);
buttonLay->addWidget(btn4);
tabLay->addWidget(tabView);
gridLay->addWidget(lbl1, 0, 0);
gridLay->addWidget(lbl2, 0, 1);
gridLay->addWidget(lbl3, 1, 0);
gridLay->addWidget(lbl4, 1, 1);
dockLay->addLayout(gridLay);
dockLay->addLayout(tabLay);
mainLayout->addLayout(dockLay);
mainLayout->addLayout(buttonLay);
mainLayout->addWidget(tableWidget);
centralWidget()->setLayout(mainLayout);
setMinimumSize(200,200);
show();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::resizeEvent(QResizeEvent * /*event*/)
{
// get label dimensions
int h = lbl1->height();
int w = lbl1->widthForHeight(h);
lbl1->setFixedWidth(w);
lbl2->setFixedWidth(w);
lbl3->setFixedWidth(w);
lbl4->setFixedWidth(w);
}
Main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
What do i want:
Set a minimum size to the whole application so that the imagewidgets do not overlap.
Make the whole app work on any PC or laptop screen with different resolutions.
The imagewidgets should take up available space while keeping the aspect ratio of the images and the QTabWidget on the right should have a fixed size.
Maybe there is an easy solution but i am bit confused with Qt Layout management system.
EDIT1: Added the image with overlapping widgets
Here is what I think is happening. When you set the pixmap like here:
QLabel::setPixmap(scaledPixmap());
The label will set the size of the images as the minimum size. And from that point on the label can not be resized any smaller.
The solution I have found around this is to set the following resize flags for the QLabel in the constructor:
QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
setSizePolicy(sizePolicy);
This way the QLabel will be resizable at all times. Or you might have to adapt the minimum width.
I am not sure if that is even it, but maybe it is a good start. Let me know what you make of this.

Using QPainter to draw a line between QWidgets

I'm working on an application where I need to be able to draw a line between two QWidget objects. I have tried quite a few things, but my current attempt (which I think is in the right direction I just think I'm missing something) is to have the containing widget (which I called DrawWidget and which holds the QGridLayout that the QWidget objects are added to) override the paintEvent method and call the QPainter::drawLine() function.
The issues I'm having are that:
No matter how I try to get the position of the widgets, the endpoints of the line are always in the wrong place
Whenever I try to draw a second line, the first line that I drew gets erased.
Here is the paintEvent function of the containing widget:
void paintEvent(QPaintEvent *)
{
if (!drewSinceUpdate){
drewSinceUpdate = true;
QPainter painter(this);
painter.setPen(QPen(Qt::black));
painter.drawLine(start->geometry().center(), end->geometry().center());
}
}
I have tried many different ways to get the correct position of the widgets in the last line of paintEvent, which I will post some of the ways (I can't remember all of them):
painter.drawLine(start->pos(), end->pos());
painter.drawLine(start->mapToGlobal(start->geometry().center()), end->mapToGlobal(end->geometry().center()));
painter.drawLine(this->mapToGlobal(start->geometry().center()), this->mapToGlobal(end->geometry().center()));
painter.drawLine(start->mapTo(this, start->pos()), end->mapTo(this, end->pos()));
painter.drawLine(this->mapFrom(start, start->pos()), this->mapFrom(end, end->pos()));
And just to make my question clear, here is an example of what I am looking for, taken from QT Diagram Scene Example:
But this is what I end up getting:
Thank you for any help you can provide.
NOTE:
-start and end are both QWidget objects which I passed in using another method
-The hierarchy relevant to DrawWidget is:
QMainWindow
->QScrollArea
->DrawWidget
->QGridLayout
->Items <-- These are the things I want to connect
EDIT: To make a Complete and Verifiable example, here is the entirety of the relevant code.
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QScrollBar>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
// Setting up the relevant hierarchy
ui->setupUi(this);
scrollArea = new QScrollArea();
setCentralWidget(scrollArea);
drawWidget = new DrawWidget();
gridLayout = new QGridLayout();
gridLayout->setSpacing(300);
drawWidget->setLayout(gridLayout);
scrollArea->setWidget(drawWidget);
scrollArea->setWidgetResizable(true);
AddItemSlot();
QApplication::connect(scrollArea->horizontalScrollBar(), SIGNAL(rangeChanged(int,int)), this, SLOT(scrollHorizontal()));
}
// This is just creating a single one of the example widgets which I want to connect
QWidget* MainWindow::CreateNewItem(){
QWidget* itemWidget = new QWidget();
itemWidget->setStyleSheet("background-color: lightgray");
QHBoxLayout* singleItemLayout = new QHBoxLayout();
itemWidget->setLayout(singleItemLayout);
QTextEdit* textEdit = new QTextEdit(std::to_string(counter++).c_str());
textEdit->setStyleSheet("background-color:white;");
singleItemLayout->addWidget(textEdit);
QVBoxLayout* rightSidePanel = new QVBoxLayout();
rightSidePanel->setAlignment(Qt::AlignTop);
QPushButton* button1 = new QPushButton("Top Button");
QApplication::connect(button1, SIGNAL(clicked(bool)), this, SLOT(AddItemSlot()));
rightSidePanel->addWidget(button1);
QWidget* rightPanelWidget = new QWidget();
rightSidePanel->setMargin(0);
rightPanelWidget->setLayout(rightSidePanel);
singleItemLayout->addWidget(rightPanelWidget);
itemWidget->setLayout(singleItemLayout);
itemWidget->setMinimumWidth(400);
itemWidget->setFixedSize(400,200);
return itemWidget;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::scrollHorizontal()
{
scrollArea->ensureWidgetVisible(noteItems.back());
}
void MainWindow::AddItemSlot()
{
QWidget* w = CreateNewItem();
gridLayout->addWidget(w,currRow, currCol++);
if (!noteItems.empty()){
drawWidget->updateEndpoints(noteItems.back(), w);
}
noteItems.push_back(w);
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QGridLayout>
#include <QWidget>
#include <QMainWindow>
#include <QScrollArea>
#include <drawwidget.h>
#include "drawscrollarea.h"
#include <vector>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void scrollHorizontal();
void AddItemSlot();
private:
Ui::MainWindow *ui;
QWidget* CreateNewItem();
int counter = 0, currCol = 0, currRow = 0;
std::vector<QWidget*> noteItems;
QScrollArea* scrollArea;
DrawWidget* drawWidget;
QGridLayout* gridLayout;
};
#endif // MAINWINDOW_H
DrawWidget.cpp:
#include "drawwidget.h"
#include <QDebug>
#include <QRect>
DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
{
}
void DrawWidget::paintEvent(QPaintEvent *)
{
if (!drewSinceUpdate){
drewSinceUpdate = true;
QPainter painter(this);
painter.setPen(QPen(Qt::black));
for (ConnectedPair pair : items){
const QWidget* from = pair.from;
const QWidget* to =pair.to;
QPoint start = from->mapToGlobal(from->rect().topRight() + QPoint(0, from->height()/2));
QPoint end = to->mapToGlobal(to->rect().topLeft() + QPoint(0, to->height()/2));
painter.drawLine(mapFromGlobal(start), mapFromGlobal(end));
}
}
}
void DrawWidget::updateEndpoints(QWidget* startIn, QWidget* endIn){
drewSinceUpdate = false;
items.push_back(ConnectedPair{startIn, endIn});
}
DrawWidget.h
#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QtCore>
#include <vector>
class DrawWidget : public QWidget
{
Q_OBJECT
public:
explicit DrawWidget(QWidget *parent = nullptr);
void updateEndpoints(QWidget* startIn, QWidget* endIn);
virtual void paintEvent(QPaintEvent *);
signals:
private:
struct ConnectedPair {
const QWidget* from;
const QWidget* to;
};
std::vector<ConnectedPair> items;
bool drewSinceUpdate = true;
};
#endif // DRAWWIDGET_H
For this case we use the function mapToGlobal() and mapfromGlobal(), since pos() returns a position with respect to the parent and this can cause problems if the widget has different parents.
drawwidget.h
#ifndef DRAWWIDGET_H
#define DRAWWIDGET_H
#include <QWidget>
class DrawWidget : public QWidget
{
Q_OBJECT
public:
explicit DrawWidget(QWidget *parent = nullptr);
void addWidgets(const QWidget *from, const QWidget *to);
protected:
void paintEvent(QPaintEvent *);
private:
struct WidgetsConnected {
const QWidget* from;
const QWidget* to;
};
QList<WidgetsConnected> list;
};
#endif // DRAWWIDGET_H
drawwidget.cpp
#include "drawwidget.h"
#include <QPainter>
DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent)
{
}
void DrawWidget::addWidgets(const QWidget * from, const QWidget * to)
{
list.append(WidgetsConnected{from , to});
update();
}
void DrawWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
for(const WidgetsConnected el: list){
const QWidget* from = el.from;
const QWidget* to = el.to;
QPoint start = from->mapToGlobal(from->rect().topRight() + QPoint(0, from->height()/2));
QPoint end = to->mapToGlobal(to->rect().topLeft() + QPoint(0, to->height()/2));
painter.drawLine(mapFromGlobal(start), mapFromGlobal(end));
}
}
The complete example can be found here.

QMdiArea is returning the wrong height and width

I am trying to arrange my subWindows in the QMdiArea vertically. I saw lot of examples online and they all were doing the same thing as I am doing here.
I have two textEdits which needs to be tiled vertically both covering half of the screen. So in the constructor of the MainWindow I add the two textEdits as subWindow to the qMdiArea and then find the height and width of the qMdiArea divide the height by 2 and resize the subWindow. Please see the code below.
My mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->showMaximized();
qMdiArea = new QMdiArea();
qTextEdit1 = new QTextEdit();
qTextEdit2 = new QTextEdit();
setCentralWidget(qMdiArea);
qMdiArea->adjustSize();
qMdiArea->addSubWindow(qTextEdit1);
qMdiArea->addSubWindow(qTextEdit2);
QPoint position(0, 0);
foreach (QMdiSubWindow *window, qMdiArea->subWindowList())
{
QRect rect(0, 0, qMdiArea->width(), qMdiArea->height() / qMdiArea->subWindowList().count());
window->setGeometry(rect);
window->move(position);
position.setY(position.y() + window->height());
}
}
MainWindow::~MainWindow()
{
delete ui;
}
My window.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMdiArea>
#include <QTextEdit>
#include <QPoint>
#include <QMdiSubWindow>
#include <QRect>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QMdiArea *qMdiArea;
QTextEdit *qTextEdit1;
QTextEdit *qTextEdit2;
};
#endif // MAINWINDOW_H
and my Main File :
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
But its not happening as expected. The window just occupy a part of the screen though they are tiled vertically. My screen resolution is 1920x1200
The height() and width() of mdiArea are invalid at that stage, because the widget hasn't been exposed/shown yet. Calling show() only schedules a widget for display, the act of sizing it and showing it on screen happens later when the control has returned to the event loop.
As a solution, you can override the resizeEvent handler. Once you do, your project will work again:
Definition in mainwindow.h:
virtual void resizeEvent(QResizeEvent *ev) override;
Implementation in mainwindow.cpp:
void MainWindow::resizeEvent(QResizeEvent *ev)
{
Q_UNUSED(ev)
QPoint position(0, 0);
foreach (QMdiSubWindow *window, qMdiArea->subWindowList())
{
QRect rect(0, 0, qMdiArea->contentsRect().width(), qMdiArea->contentsRect().height() / qMdiArea->subWindowList().count());
window->setGeometry(rect);
window->move(position);
position.setY(position.y() + window->height());
}
}
Also it seems that you don't really need to have this->showMaximized(); call inside MainWindow's constructor. You can call it from main.cpp, for example.

Ball bounce off the walls in C++ using Qt

I'm trying to create a simple animation of a ball that is wandering on a screen and simply bounces off on walls. Since I'm fairly new to C++, I've got some problems with this task. I'm also using the Qt-library.
The ball just stays on the same spot and moves back and forth a little which is odd, because I create a SceneRect with the same size as my graphicsView.
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QGraphicsScene>
#include <QtWidgets>
float movement_x = 2.5;
float movement_y = 2.0;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::showEvent(QShowEvent *event){
scene = new QGraphicsScene(this);
scene -> setSceneRect(ui->graphicsView->geometry().x(), ui->graphicsView->geometry().y(),
ui->graphicsView->geometry().width(), ui->graphicsView->geometry().height());
ui->graphicsView->setScene(scene);
QPen redpen(Qt::red);
QBrush brush(Qt::green);
//QBrush brush2(Qt::black);
QPen mypen(Qt::blue);
mypen.setWidth(7);
ellipse = scene->addEllipse(100.0,100.0,20.0,20.0,mypen,brush);
timer1 = startTimer(50);
timer2 = startTimer(600);
}
void MainWindow::timerEvent(QTimerEvent *event){
// check for radius
if(ellipse->pos().x() >= scene->sceneRect().right() || ellipse->pos().x() <= scene->sceneRect().left()){
movement_x = -movement_x;
}
if(ellipse->pos().y() >= scene->sceneRect().bottom() || ellipse->pos().y() <= scene->sceneRect().top()){
movement_y = -movement_y;
}
ellipse->moveBy(movement_x, movement_y);
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QGraphicsScene>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void showEvent(QShowEvent* event);
void timerEvent(QTimerEvent* event);
private:
Ui::MainWindow *ui;
QGraphicsScene *scene;
QGraphicsEllipseItem *ellipse;
};
#endif // MAINWINDOW_H
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.resize(800,600);
w.show();
return a.exec();
}
The initial value of pos is (0,0). Because of this your update oscillate between two values. After addEllipse you have to set an initial position within the scene rect. For example
ellipse->setPos(100,100);
You should map the ellipse position from the scene to find the boundaries :
QPoint posOfEclps = ellipse->mapToScene(ellipse->pos());
if(posOfEclps.x() >= scene->sceneRect().right() || posOfEclps.x() <= scene->sceneRect().left())
{
movement_x = -movement_x;
}
if(posOfEclps.y() >= scene->sceneRect().bottom() || posOfEclps.y() <= scene->sceneRect().top())
{
movement_y = -movement_y;
}
ellipse->moveBy(movement_x, movement_y);

How do I move a QPixMapImage around a qgraphicsview

I can add a QPixMapImage to a QGraphicsScene, but then I have two issues.
First I cannot create a pointer to my QPixmapItem declared in the header, where i can with QGraphicsScene.
I get an error "error: no matching function for call to 'QGraphicsPixmapItem::QGraphicsPixmapItem(MainWindow* const)" ... When I create my QGraphicsScene in Main the same way?
Second issue: I cannot move the QGraphicsPixmapItem around when the slider is moved (obv i won't until the pointer is working). But can I even move it, or do i have to repaint it?
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtGui>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QPixmap>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
QPixmap arrow = QPixmap::fromImage(QImage("ARROW.png"));
arrowItem = new QGraphicsPixmapItem(this);
arrowItem->setPixmap(arrow);
ui->graphicsView->setScene(scene);
ui->horizontalSlider->setMaximum(2000);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_horizontalSlider_sliderMoved(int position)
{
arrowItem->setPos(position,position);
scene->addItem(arrowItem);
}
Header:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QGraphicsPixmapItem>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QGraphicsPixmapItem *arrowItem;
QGraphicsScene *scene;
private slots:
void on_horizontalSlider_sliderMoved(int position);
};
#endif // MAINWINDOW_H
Issue #1:
There error you're getting means there is no such constructor declared for QGraphicsPixmapItem; you use either one of these:
QGraphicsPixmapItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
// ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0
#ifndef Q_QDOC
// ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
Issue#2
If I understood your question correctly you want to be able to drag your graphics items around the scene. You can switch this functionality on by using view->setDragMode method.
Please see if an example below would work for you:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QGraphicsScene* scene = new QGraphicsScene(QRect(-50, -50, 400, 200));
QPixmap image = QPixmap::fromImage(QImage("image.JPG"));
QGraphicsPixmapItem* pixMapItem = new QGraphicsPixmapItem();
pixMapItem->setPixmap(image);
scene->addItem(pixMapItem);
QGraphicsView* view = new QGraphicsView(ui->centralWidget);
view->setScene(scene);
view->setGeometry(QRect(50, 50, 400, 200));
view->setDragMode(QGraphicsView::ScrollHandDrag);
view->show();
}
hope this helps, regards