Show QListView in QMessageBox - qt

I'm completely new with QT and find it quite confusing.
I created a QListView (called "listview") and would like to show that in my QMessageBox:
const int resultInfo = QMessageBox::information(this, tr("Generate Software"),
tr("The following files will be changed by the program:"),
=> Here the QListView should show up!
QMessageBox::Yes | QMessageBox::No);
if (resultInfo != QMessageBox::Yes) {
return;
}
Is that possible somehow?

QMessageBox is designed to serve texts and buttons only. See link.
If you just want to have a "More details" text, try using detail text property. In that case, you will have to create the message box using its constructor and set the icons, texts explicitly, not using the convenient information() function.
If you still want to have a list view in the message box, you should consider using QDialog, which is the base class of QMessageBox. Small example below:
#include "mainwindow.h"
#include <QDialog>
#include <QListView>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QDialog *dialog = new QDialog{this};
dialog->setWindowTitle(tr("Fancy title"));
auto button = new QPushButton{tr("OK"), this};
connect(button, &QPushButton::clicked, dialog, &QDialog::accept);
QVBoxLayout *layout = new QVBoxLayout{dialog};
layout->addWidget(new QLabel{tr("Description"), this});
layout->addWidget(new QListView{this});
layout->addWidget(button);
dialog->show();
}
MainWindow::~MainWindow()
{
}

Related

Qt QQuickWidget conflicting with QGraphicsVideoItem

I have been using QGraphicsScene and QGraphicsVideoItem as my canvas. And to control them, I've chosen to use qml and QQuickWidget to develop custom objects easily for a different module. However, I quickly ran into an issue where the QGraphicsVideoItem would not render in the QGraphicsScene but rather inside the QQuickWidget (both when the widget is empty or with a qml source attached). And the issue seems to be reproducible using a fresh project as well just by placing an empty QQuickWidget(through qt designer) anywhere inside the main ui.
Here is the reproducible code:
#include "QtGuiApplication1.h"
QtGuiApplication1::QtGuiApplication1(QWidget *parent): QMainWindow(parent)
{
ui.setupUi(this);
QGraphicsView* view = new QGraphicsView(ui.widget);
QGraphicsScene* scene = new QGraphicsScene();
QGraphicsVideoItem* video = new QGraphicsVideoItem();
QMediaPlayer* player = new QMediaPlayer();
QUrl path = QUrl::fromLocalFile("D:/My Documents/Videos/XIII.mp4");
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(view);
ui.widget->setLayout(layout);
video->setFlags(QGraphicsVideoItem::ItemIsMovable | QGraphicsVideoItem::ItemIsFocusable | QGraphicsVideoItem::ItemIsSelectable);
video->setPos(100, 100);
//view->setSceneRect(QRectF(QPointF(100, 100), QPointF(800, 600)));
view->setScene(scene);
player->setMedia(path);
player->setVideoOutput(video);
scene->addItem(video);
player->play();
view->show();
}
#pragma once
#include "ui_QtGuiApplication1.h"
#include <QtCore>
#include <QDebug>
#include <QGraphicsVideoItem>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QMediaPlayer>
#include <QUrl>
#include <QString>
class QtGuiApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication1(QWidget *parent = Q_NULLPTR);
private:
Ui::QtGuiApplication1Class ui;
};
The issue immediately went away when I removed the widget from the ui file as well. So am I missing something here?
When you call ui.widget->setLayout(layout); you break the layout that was set in Qt Designer.
Instead of programmatically creating the QGraphicsView and QVBoxLayout in your *.cpp file, add them all in Qt Designer.
(If the issue still persists, please edit your original post and include your *.ui file)

QGraphicsSceneMouseEvent get position will not work [duplicate]

This question already has an answer here:
Qt Widgets and derived classes
(1 answer)
Closed 3 years ago.
I am trying to make an application with a QGraphicsView in it. I tried to get the position of a mouse when the mouse was pressed with QGraphicsSceneMouseEvent, but it doesn't seem to work. The entire function is never called when I press the mouse.
I would like to make an application that can load an image into the QGraphicsView and then when you press the mouse button, it should add a small circle.
This is my code:
dialog.cpp:
#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
ui->graphicsView = new GraphicsView();
}
Dialog::~Dialog()
{
delete ui;
}
graphicsview.h:
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QMouseEvent>
#include <QDebug>
class GraphicsView : public QGraphicsView
{
public:
GraphicsView();
protected:
void mousePressEvent(QMouseEvent *event) override;
private:
QGraphicsScene *scene;
};
#endif // GRAPHICSVIEW_H
graphicsview.cpp:
#include "graphicsview.h"
GraphicsView::GraphicsView()
{
scene = new QGraphicsScene();
this->setScene(scene);
}
void GraphicsView::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
qDebug() << "The left button was pressed!";
}
}
You're almost there.
Just change GraphicsView::GraphicsView() to:
GraphicsView::GraphicsView(QWidget *parent=nullptr) : QGraphicsView(parent) {}
and change ui->graphicsView = new GraphicsView(); to
QVBoxLayout *verticalLayout = new QVBoxLayout(this);
verticalLayout->addWidget(new GraphicsView(this));
This will make the graphics view a parent of the dialog. Make sure that your dialog doesn't have anything in it when you add the code above. Alternatively, you can add a vertical layout to the dialog in your dialog.ui file and do
ui->verticalLayout->addWidget(new GraphicsView(this));
I believe that solves your problem. Respond if you still have any issues.
Make sure you always have a parent parameter. Without it, you're not telling your program where it's supposed to add your widget.

How can I access the content of a widget outside the constructor?

I want to display the content I wrote in the QLineEdit widget after clicking on the QPushButton with the function ShowMessage(). How can I access that content outside of the constructor?
Tried putting the QLineEdit object I created in to a private variable.
My CPP file
#include "manualwidget.h"
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QMessageBox>
ManualWidget::ManualWidget(QWidget *parent) : QWidget(parent)
{
QLabel *label = new QLabel(this);
QLineEdit *lineEdit = new QLineEdit(this);
QPushButton *pushButton = new QPushButton(this);
QHBoxLayout *layout = new QHBoxLayout();
label->setText("Enter text:");
pushButton->setText("Ok");
layout->addWidget(label);
layout->addWidget(lineEdit);
layout->addWidget(pushButton);
setLayout(layout);
connect(pushButton,SIGNAL(clicked()),this ,SLOT(showMessage()));
connect(lineEdit, SIGNAL(returnPressed()),this, SLOT(showMessage()));
}
void ManualWidget::showMessage(){
QMessageBox::information(this, "Message", "The text entered in the "
"manual widget window is:\n" + m_lineEdit->text());
}
My header file
#ifndef MANUALWIDGET_H
#define MANUALWIDGET_H
#include <QWidget>
#include <QLineEdit>
class ManualWidget : public QWidget
{
Q_OBJECT
public:
explicit ManualWidget(QWidget *parent = nullptr);
signals:
public slots:
private slots:
void showMessage();
private:
QLineEdit m_lineEdit;
};
#endif // MANUALWIDGET_H
#eyllanesc suggestion might work, but it should not be a prefered approach. Qt has its' own memory model, and usage of it should be prefered. Thus, "QLineEdit m_lineEdit" should be changed to e.g. "QLineEdit* m_lineEdit", and in constructor you should initialize it in the following way:
// Instance of the QLineEdit will be owned by the ManualWidget which is part of Qt memory management now.
m_lineEdit = new QLineEdit(this);
Then, the following line:
layout->addWidget(lineEdit);
Can be changed to:
layout->addWidget(m_lineEdit);
Why is it bad to use "QLineEdit m_lineEdit"? Because Qt might want to destroy this object for some reason (you still can call m_lineEdit.deleteLater()) and you might end up in the "double destruction" situation which would result in app being crashed. You can say that in this way conflicting memory models would interact.

Dynamically adding widgets to gridLayout Qt

I am having a bit of difficulty with some code. I am super rather new to Qt so it is entirely possible that I am simply ignorant to the problem I am having.
Basically, I am blocking out a program so that I can add the specifics of it later. I want to be able to create a grid of buttons, and when one of those buttons is pressed, another shape to replace it.
I am able to make my button grid, have it be scrollable, and have the button call it its position on the grid when pressed. However, when I try and use those coordinates to add another button to the grid, Qt crashes.
Here's my code so far:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <cmath>
#include <QLabel>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QApplication>
#include <QPushButton>
#include <QScrollArea>
#include <QDebug>
#include <QString>
#include <QSignalMapper>
#include <QStringList>
#include <QLayoutItem>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
populateViewGrid(); //I wanted to see if I could add in a scrollbar
//from outside the main window. Could this be causing
// the issue?
}
void MainWindow::populateViewGrid()
{
QScrollArea*scrollArea = new QScrollArea(this);
QWidget*central = new QWidget(this);
QGridLayout*gridLayout = new QGridLayout(central);
QSignalMapper *signalMapper = new QSignalMapper(central);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
QString position= QString("%1,%2").arg(i).arg(j);
QPushButton* button = new QPushButton("addTrack",central);
gridLayout->addWidget(button, i, j);
connect(button, SIGNAL(clicked()),signalMapper, SLOT(map()));
signalMapper->setMapping(button, position);
}
}
connect(signalMapper, SIGNAL(mapped(QString)),this, SLOT(addTrack(QString )));
central->setLayout(gridLayout);
scrollArea->setWidget(central);
setCentralWidget(scrollArea);
}
void MainWindow::addTrack(QString position)
{
QStringList query = position.split(",");
int x;
x=query.at(0).toInt();
int y;
y=query.at(1).toInt() ;
QPushButton *Ifthisworks=new QPushButton(this);
//This first line is where is crashes. I know this due to having the code
//laced with qDebugs. From all of my google searches and such, it seems that
// something simple should be wrong and I can't find it.
QLayoutItem * existingitem = gridLayout->itemAtPosition(x, y);
if(existingitem) {
gridLayout->removeItem(existingitem);
delete existingitem;
}
// before I included the above to remove the button from the grid point, the
//program would crash here.
gridLayout->addWidget(Ifthisworks, x, y);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <cmath>
#include <QLabel>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QApplication>
#include <QPushButton>
#include <QMainWindow>
#include <QScrollArea>
#include <QSignalMapper>
#include <QHash>
//unrelated question, do I need the above in my code? I know not all of them
//used, but do I need includes in this file as well?
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void populateViewGrid();
QGridLayout *gridLayout;
public slots:
void addTrack(QString);
private:
QScrollArea*scrollArea;
QWidget * central;
QPushButton *Ifthisworks;
QSignalMapper *signalMapper;
QPushButton *clockViews;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
If you could help me understand how to not make Qt crash there and also add a button, that would be fantastic =)
So some background real quick incase you are looking at my code and are scratching your head. I'm a mechanical engineer who should have probably been an electrical or computer engineer and knows enough about coding to get myself into these kinds of messes. For the most part, I searched for what I wanted Qt to do and hacked it all together to hopefully make it work. Any bit of deeper understanding you can share would be more than welcome.
Thank you for your time.
You are initializing a local variable called gridLayout in your MainWindow::populateViewGrid() method:
QGridLayout*gridLayout = new QGridLayout(central);
Then in your MainWindow::addTrack(QString position) method, you are trying to access the member variable called gridLayout which is never initialized.
To fix this, simply initialize the member variable instead of creating a local variable in your MainWindow::populateViewGrid() method:
gridLayout = new QGridLayout(central);
You are doing the same mistake with your other member variables as well. Fix them the same way.
I would go for a different implementation.
Move gridlayout, signalmapper,... to be class members. I personally like also to keep a list of my widgets QList<QPushButton*> for manually deleting or keeping a button cache.
Make the signalmapper to map to index in list or QWidget*. For the example i`ll go with the QWidget* pointer.
QPushButton *newButton = new QPushButton("The new Thing");
QPushButton *oldButton = static_cast<QPushButton*>(widgetPointer);
gridLayout->replaceWidget(oldButton ,newButton);
buttonList->takeAt(buttonList->indexOf(oldButton))->deleteLater()); //if you keep a list..
buttonList->insert(buttonList->indexOf(oldButton),newButton);

showing hidden dockwidget in qt

hi i create a dockwidget which i am starting it as hidden. The problem is that afterwards i cannot show it, while i can get the status correctly from the isHidden() function. The weird thing is that if i start the dockwidget not hidden, it works perfect. I am including an example that reproduces this strange behaviour.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void showDock();
private:
Ui::MainWindow *ui;
QDockWidget *dock;
QPushButton *button;
};
#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);
// QMainWindow mainWindow;
// QDockWidget *dock = new QDockWidget(&mainWindow);
QDialog *dockDialog = new QDialog(this); // <---------edit: you need to create a parent widget for the dock
dock = new QDockWidget(dockDialog);
dock->setStyleSheet("QDockWidget { font: bold }");
dock->setFloating(true);
dock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
QAbstractButton *floatButton = dock->findChild<QAbstractButton*>("qt_dockwidget_floatbutton");
if(floatButton)
floatButton->hide();
dock->setAllowedAreas( Qt::NoDockWidgetArea );
dock->setWindowTitle("Tools");
this->addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
QMainWindow *window = new QMainWindow(dock); // <------edit: set the dock to be the parent for the window
window->setWindowFlags(Qt::Widget);
QToolBar *bar = new QToolBar(window);
bar->setMovable(false);
bar->addAction("Select");
bar->addAction("Polygon");
bar->addAction("Brush");
bar->addAction("Erazer");
bar->addSeparator();
bar->addAction("Mark");
bar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
bar->setOrientation(Qt::Vertical);
window->addToolBar(Qt::LeftToolBarArea, bar);
window->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
window->setParent(dock);
dock->setWidget(window);
dock->hide(); // <------------ comment this line and it will work, edit: you do not need to do that anymore, it is working nicely now
button = new QPushButton("show", this);
button->setCheckable(true);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(showDock()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showDock()
{
// qDebug() << "hello";
if(button->isChecked()){
if(dock->isHidden()){
qDebug() << "hidden";
dock->setFloating(true); // <-----edit: you need to add these lines in order to be able to see the dialog that contains the dock widget, i do not know why i need to that again since in the initialization i already specifying that my dock is floatable
QAbstractButton *floatButton = dock->findChild<QAbstractButton*>("qt_dockwidget_floatbutton"); // <---------edit: add this lines in order to get rid off the floating button
if(floatButton)
floatButton->hide(); // <----edit: the same as previous
dock->show();
}
}
if(!button->isChecked()){
if(!dock->isHidden()){
qDebug() << "not hidden";
dock->hide();
}
}
}
as it is now the above code the dockwidget is not appearing in the screen. If you try to comment the line that i am specifying in the mainwindow.cpp it works, but the point is that i want to start the dockwidget hidden. Does someone have any idea, of what is happening.
Thanks.
Parent of the QDock control should be your window widget, and not object of the MainWindow class.
So, you need to replace this:
dock = new QDockWidget(this);
with this:
QMainWindow *window = new QMainWindow(0); // I smell a potential leak here (set the parent!)
dock = new QDockWidget(window);
Control is visible when you press Show button in the first case, too, but it is somewhere outside the window, so you may not see it. Also, there is no need to create separate instance of QMainWindow inside class that is already inheriting QMainWindow.
I see you show()/hide() your dockwidget. I haven't tried it myself but maybe you should hide and show the dockwdiget with the QDockWidget::toggleViewAction method.

Resources