Something seems wrong while dragging QSplitter? - qt

A qsplitter has been used in my application, and OpaqueResize is set to 'false',while dragging the splitter handle, the widget becoming smaller is repainted continuously, this is not right. What I thought is that the QWidgets on both sides of the splitter handle should not receive any signals about repaint or resize until mouseRelease.This issue troubles me several days, if anyone knows about how to deal with it, please give me a hand, thank you.
Qt5.11.2 on Windows10 64-bits
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// left
ui->widget_2->bgColor = QColor(255,0,0);
ui->widget_2->tag = 0;
// right
ui->widget_3->bgColor = QColor(0,0,255);
ui->widget_3->tag = 1;
}
MainWindow::~MainWindow()
{
delete ui;
}
MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
{
bgColor = QColor(255,255,255);
tag = 0;
}
void MyWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent( event );
QPainter painter(this);
QBrush brush( bgColor );
painter.fillRect( event->rect(), brush );
qDebug() << "paintEvent:tag="<<tag;
}

Related

stack widget pages using pushbutton in Qt

How to navigate QStackWidget pages using QPushButtons?
Which method needs to be called whenever pushbutton is clicked, so that it opens a particluar stackwidget page.
Thanks & Regards,
QStackedWidget has a method .setCurrentIndex(int) which you can use to switch to a different page. You can use that method in combination with clicked() signal of QPushButton to change the current stacked widget page.
Example:
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
//initially set current page to 0
ui->stackedWidget->setCurrentIndex(0);
//suppose we have buttons button1 and button2
connect(button1, &QPushButton::clicked, this, [=]() {
//set page to 1
ui->stackedWidget->setCurrentIndex(1);
});
connect(button2, &QPushButton::clicked, this, [=]() {
//set page to 2
ui->stackedWidget->setCurrentIndex(2);
});
}
You can also use normal function slots instead of lambda functions:
//mainwindow.h file
class MainWindow{
//...
private slots:
void onButton1Clicked();
void onButton2Clicked();
}
//mainwindow.cpp file
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
//...
connect(button1, &QPushButton::clicked, this, &MainWindow::onButton1Clicked);
connect(button2, &QPushButton::clicked, this, &MainWindow::onButton2Clicked);
}
void MainWindow::onButton1Clicked()
{
ui->stackedWidget->setCurrentIndex(1);
}
void MainWindow::onButton2Clicked()
{
ui->stackedWidget->setCurrentIndex(1);
}

Program crashed when calling QColorDialog into a slot function connected to a widget defined thanks to qt-designer

I designed a push button thanks to Qt-designer, named colorizeButton, and connected it to a slot in my code :
.h :
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
Draw * draw;
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots :
void colorize();
private:
Ui::MainWindow *ui;
};
.cpp, constructor of my QMainWindow :
draw = new Draw(parent);
setCentralWidget(draw);
ui->setupUi(this);
ui->colorizeButton->setAutoDefault(false);
connect(ui->colorizeButton, SIGNAL(clicked()), this, SLOT(colorize()));
.cpp, after :
void MainWindow::colorize() {
cout << "colorize()" << endl;
QColor color = QColorDialog::getColor(Qt::black, draw);
draw->Draw::setColor(color);
}
When I run this and click on the colorizeButton, "colorize()" is printed out, but then the program crashes. Do you understand why ?
I am confused because, before that, I used a QAction and a similar connection (it was just "triggered()" instead of "clicked") and it worked : I could interact with the QColorDialog.
Thank you by advance ! :D
This line of code looks odd:
draw->Draw::setColor(color);
I suppose that Draw's base class is QWidget and you want to change color of its background. You can do it like this:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
draw = new QWidget(); // No need to set its parent because setCentralWidget sets it
}
void MainWindow::on_btnColorize_clicked()
{
QColor color = QColorDialog::getColor(Qt::black, draw); // I do not know why you use draw as a parent for QColorDialog
QPalette pal = palette();
pal.setColor(QPalette::Background, color);
draw->setAutoFillBackground(true);
draw->setPalette(pal);
this->setCentralWidget(draw);
}
Note that in such case draw will take the whole MainWindow.

QRubberBand and MPlayer in QLabel

I have already tried many solution that are provided on stackoverflow to make it transparent.
I want to make QRubberBand transparent and i am also facing problem regarding that green color which is due to mplayer.
#include "physician.h"
#include "ui_physician.h"
Physician::Physician(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Physician)
{
ui->setupUi(this);
ui->sendROIButton->setStyleSheet(
"background-color: #d9d9d9;"
"border-radius: 10px;"
"color: Black; "
"font-size: 15px;"
);
}
Physician::~Physician()
{
delete ui;
}
void Physician::mouseMoveEvent(QMouseEvent *e)
{
rubberBand->hide();
bottomRight = e->pos();
QRect rect = QRect(topLeft, bottomRight).normalized();
rubberBand->setGeometry(rect);//Area Bounding
QToolTip::showText(e->globalPos(), QString("%1,%2")
.arg(rubberBand->size().width())
.arg(rubberBand->size().height()), this);
}
void Physician::mousePressEvent(QMouseEvent *e)
{
wWidth=ui->videoShowLabel->width();
wHeight = ui->videoShowLabel->height();
rubberBand->setGeometry(QRect(0, 0, 0, 0).normalized());
rubberBand->hide();
topLeft = e->pos();
}
void Physician::mouseReleaseEvent(QMouseEvent *e){
rubberBand->show();
}
void Physician::on_manualROIRadioButton_clicked()
{
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
}
void Physician::on_autoROIRadioButton_clicked()
{
QString winNuber= QString::number((int)(ui->videoShowLabel->winId()));
QStringList argsList ;
argsList << "-slave" << "-quiet" << "-wid" << winNuber << "zoom" << "-
vo" << "gl" << "C:/../../../Physician21/PhotoshopQML.mkv";
mplayer_proc = new QProcess;
mplayer_proc-
>start("C:/../../../PhysicianTest/mplayer/mplayer.exe",argsList);
}
Firstly, regarding "QRubberBand should work only on that QLabel". You need to make the QLabel the parent of the QRubberBand to achieve that.
Secondly, regarding transparency I assume you mean that the output from mplayer should be visible through the rectangle painted by the QRubberBand? I'm not sure you will be able to do that. Doing so would required the rubber band painting logic to act as a compositor but in order to do that it needs to know both the source and destination(mplayer) images. Since mplayer draws directly on the underlying native window Qt has know knowledge of the current destination image and so can not merge the source image with it. I think your best bet would be to find/generate a style that causes QRubberBand to draw the rectangle outline only -- not sure if that's possible. You could subclass it and do your own painting with something like...
class rubber_band: public QRubberBand {
using super = QRubberBand;
public:
template<typename... Types>
explicit rubber_band (const Types &... args)
: super(args...)
{}
protected:
virtual void paintEvent (QPaintEvent *event) override
{
QPainter painter(this);
painter.setPen(Qt::red);
painter.setBrush(Qt::NoBrush);
painter.drawRect(rect().adjusted(0, 0, -1, -1));
}
};
The above could still leave visual artifacts on the widget though.

Drawing a rectangle (or anything) on QGraphicsView

I'm using QtCreator to build an interface application.
I'm just getting used to Qt and toying around trying to draw stuff on a QtGraphicsView.
Since I created my interface with the editor, I am retrieving my objects in the code like so (please tell me if this is wrong).
this->m_graphView = this->findChild<QGraphicsView *>("graphicsView");
this->m_graphScene = this->m_graphView->scene();
I have buttons on the interface and already created slots to react to the clicked event.
I'm just trying to draw something (anything) on the graphics view that is on my MainWindow (geometry : [(10,10), 320x240]).
I've been reading examples online and I can't make anything work.
My current code is as follows :
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->m_graphView = this->findChild<QGraphicsView *>("graphicsView");
this->m_graphScene = this->m_graphView->scene();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnDown_clicked()
{
qDebug() << "STUB : button DOWN";
m_graphScene->addLine(0, 0, 42, 42, QPen(QBrush(Qt::black),1));
m_graphView->show();
}
void MainWindow::on_btnLeft_clicked()
{
qDebug() << "STUB : button LEFT";
}
void MainWindow::on_btnUp_clicked()
{
qDebug() << "STUB : button UP";
}
void MainWindow::on_btnRight_clicked()
{
qDebug() << "STUB : button RIGHT";
}
void MainWindow::on_btnShoot_clicked()
{
qDebug() << "STUB : button SHOOT";
}
But annoyingly, it doesn't draw anything and I even get this error when the addLine method is called
QGraphicsScene::addItem: item has already been added to this scene
What's wrong in my code and/or my ways of doing things?
I just want to draw something but can't make it, thank you.
retrieving widget in form
you can get graphicsView pointer (and its scene) more easier.
"ui" member has the pointer to widgets arranged in .form file.
(If you please, see "ui_mainwindow.h" file)
// assign to pointer
QGraphicsView *view = ui->graphicsView;
view->...
// or directly (I like this)
ui->graphicsView->...
so, Mainwindow class don't need "m_graphicsView" member.
graphics view
QGraphicsView need to set scene.(It has no scene at first)
We have to create QGraphicsScene ourselves.
So Mainwindow class need "m_graphicsScene" member.
m_graphicsScene = new QGraphicsScene(this);
ui->graphicsView->setScene(m_graphicsScene);
drawing more easier
If you just want to draw something, you can override "paintEvent" method.
PaintEvent is QWidget's virtual method.
in .h file:
protected:
void paintEvent(QPaintEvent *event);
in .cpp file:
void MainWindow::paintEvent(QPaintEvent *event)
{
// unuse
Q_UNUSED(event);
// pass "this" pointer to painter
QPainter painter(this);
// setPen
// QPen can take "Qt::black" directly as first arg (without QBrush() constructor)
painter.setPen(QPen(Qt::black), 1);
// draw line
painter.drawLine(0, 0, 42, 42);
}
please enjoy Qt!

Centering widgets in a dynamic layout?

I'm using the answer to this SO question to make a custom image widget which automatically scales correctly. It works fine but now I am trying to center the image widget instance at the center of my main window.
My idea was to create a QHBoxLayout, add the image widget to that and then add the hBox instance to the ui->verticalLayout.
Doesn't work. The image still displays flush left with the error message: QLayout: Attempting to add QLayout "" to MainWindow "MainWindow", which already has a layout
I then tried a few variations on 'setAlignment` but then the image doesn't appear at all. My simple test code is below.
What am I missing here?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix;
pix.load("/Users/home/Desktop/test.jpg");
ImageLabel2* image = new ImageLabel2(this);
image->setPixmap(pix);
QHBoxLayout* hbox = new QHBoxLayout(this);
hbox->addWidget(image);
// hbox->setAlignment(image,Qt::AlignCenter);
hbox->setAlignment(Qt::AlignHCenter);
// ui->verticalLayout->addLayout(hbox);
ui->verticalLayout->addLayout(hbox);
// ui->verticalLayout->addWidget(image);
// ui->verticalLayout->setAlignment(image,Qt::AlignCenter);
// ui->verticalLayout->setAlignment(Qt::AlignHCenter);
}
Try this:
QHBoxLayout* hbox = new QHBoxLayout(this);
hbox->addStretch();
hbox->addWidget(image);
hbox->addStretch();
None of the suggestions here worked for me. Don't know why and it seems hard to debug layout problems
However a reply to my question on the Qt Project.org site works perfectly. So not my solution but I am posting it here since this "centering/resizing image" issue seems a common problem.
class CustomWidget : public QWidget {
public:
CustomWidget(const QPixmap &p, QWidget* parent = 0)
: QWidget(parent), pixmap(p) {}
void paintEvent(QPaintEvent * e)
{
QRect srcRect(QPoint(), pixmap.size());
QSize dstSize = srcRect.size().scaled(
e->rect().size(), Qt::KeepAspectRatio);
QRect dstRect(QPoint((width() - dstSize.width())/2,
(height() - dstSize.height())/2), dstSize);
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
p.drawPixmap(dstRect, pixmap, srcRect);
}
private:
QPixmap pixmap;
};
and then in the main window:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setCentralWidget(new CustomWidget(QPixmap("test.png")));
}
main window(QMainwindow) API setCentralWidget to align the widget on center.
Note:Concept of centrewidget, is to differentiate the docking area( Left, Right, Bottom, Top ).
with out a centre how some one know who is where. when we are developing with QMainWindow, you can see in UI_MainWindow.h, setting Centrewidget with dummy QWidget
Below code will work
#include "mainwindow.h"
#include <QLabel>
#include <QHBoxLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindowClass)
{
ui->setupUi(this);
QPixmap pix;
pix.load("C:\\Users\\user\\Desktop\\Uninstallation failure2.png");
//Replace with ImageLabel2
QLabel* image = new QLabel(this);
image->setPixmap(pix);
QHBoxLayout* hbox = new QHBoxLayout(this);
hbox->addWidget(image);
QWidget* centreWidget = new QWidget();
//QMainwindow, having a feature called centreWidget, to set the layout.
centreWidget->setLayout( hbox );
setCentralWidget( centreWidget );
}
MainWindow::~MainWindow()
{
}

Resources