I used the QT Designer to create a simple dialog and put a pushbutton on it. Then I added a custom slot on pressed() signal called test_button(). I see the generated code and can see that there is a setupUI function that has the following in it:
QObject::connect(pushButton, SIGNAL(clicked()), TestUIClass, SLOT(test_button()));
I have a testui.cpp and a testui.h:
#include <QtWidgets/QMainWindow>
#include "ui_testui.h"
class TestUI : public QMainWindow
{
Q_OBJECT
public:
TestUI(QWidget *parent = 0);
~TestUI();
virtual void test_button();
private:
Ui::TestUIClass ui;
};
This is the testui.cpp
#include "testui.h"
#include <QMessageBox>
TestUI::TestUI(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
TestUI::~TestUI()
{
}
void TestUI::test_button()
{
QMessageBox msgBox;
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
}
My understanding is this is all I have to do, but I cant get the message box to come up.
/********************************************************************************
** Form generated from reading UI file 'testui.ui'
**
** Created by: Qt User Interface Compiler version 5.9.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_TESTUI_H
#define UI_TESTUI_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_TestUIClass
{
public:
QWidget *centralWidget;
QPushButton *pushButton;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *TestUIClass)
{
if (TestUIClass->objectName().isEmpty())
TestUIClass->setObjectName(QStringLiteral("TestUIClass"));
TestUIClass->resize(600, 400);
centralWidget = new QWidget(TestUIClass);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
pushButton = new QPushButton(centralWidget);
pushButton->setObjectName(QStringLiteral("pushButton"));
pushButton->setGeometry(QRect(120, 70, 187, 57));
TestUIClass->setCentralWidget(centralWidget);
menuBar = new QMenuBar(TestUIClass);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 600, 47));
TestClass->setMenuBar(menuBar);
mainToolBar = new QToolBar(TestUIClass);
mainToolBar->setObjectName(QStringLiteral("mainToolBar"));
TestUIClass->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(EyeGazeUIClass);
statusBar->setObjectName(QStringLiteral("statusBar"));
TestUIClass->setStatusBar(statusBar);
retranslateUi(TestUIClass);
QObject::connect(pushButton, SIGNAL(clicked()), TestUIClass, SLOT(test_button()));
QMetaObject::connectSlotsByName(TestUIClass);
} // setupUi
void retranslateUi(QMainWindow *TestUIClass)
{
TestUIClass->setWindowTitle(QApplication::translate("TestUIClass", "TestUI", Q_NULLPTR));
pushButton->setText(QApplication::translate("TestUIClass", "PushButton", Q_NULLPTR));
} // retranslateUi
};
namespace Ui {
class TestUIClass: public Ui_TestUIClass {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_TestUI_H
First, you need to tell Qt that your slots actually are slots:
public slots: // or protected/private
void test_button();
There is no need for having the slot virtual...
Second, slots for 'clicked' signal are expected to accept a boolean parameter:
void test_button(bool);
For a normal push button, you can ignore the value, though.
Finally, but that's just a hint: Qt introduced with version 5 a new syntax for connecting signals/slots:
QObject::connect(pushButton, &QPushButton::clicked, theUI, &TestUIClass::test_button);
I prefer it, but it is up to you which one you use...
Related
I want to start my QT6 Application, but got exit code 139 (interrupted by signal 11: SIGSEGV).
Login extends QMainWindow with the following code in the main.cpp:
#include <QApplication>
#include <QPushButton>
#include "Login.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
auto login = new Login();
a.setActiveWindow(login);
login->show();
return a.exec();//QApplication::exec();
}
Edit: Adding Code of my Login.h and Login.cpp to provide minimal working example.
My Login.h:
#ifndef RESTCLIENT_LOGIN_H
#define RESTCLIENT_LOGIN_H
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include "QMainWindow"
QT_BEGIN_NAMESPACE
namespace Ui { class Login; }
QT_END_NAMESPACE
class Login : public QMainWindow {
Q_OBJECT
QPushButton * loginButton;
QLineEdit * passwordInput;
QLineEdit * usernameInput;
public slots:
void buttonPressed();
public:
explicit Login(QWidget *parent = nullptr);
~Login() override;
private:
Ui::Login *ui;
};
#endif //RESTCLIENT_LOGIN_H
And Login.cpp:
#include "Login.h"
#include "ui_Login.h"
Login::Login(QWidget *parent) :
QMainWindow(parent), ui(new Ui::Login) {
ui->setupUi(this);
QObject::connect(loginButton, &QPushButton::clicked, this, &Login::buttonPressed);
this ->setCentralWidget(new QWidget(this));
}
Login::~Login() {
delete ui;
}
void Login::buttonPressed() {
//todo process login
}
There is no more errors when running it, as far as I undestand it, there is no problem with finding it.
My Login GUI is very simple, I'm connecting my loginButton to the buttonPressed method in the Login.cpp, but that should be fine.
My Login.h is basically method definiton and definition of the QT elements.
Some help would be very nice, cause I can't find any usefull stuff about this (As you see, I'm new to c++ and QT)
Editi 2:
my ui_login.h:
/********************************************************************************
** Form generated from reading UI file 'Login.ui'
**
** Created by: Qt User Interface Compiler version 6.2.4
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_LOGIN_H
#define UI_LOGIN_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Login
{
public:
QLabel *label;
QLabel *label_2;
QLineEdit *usernameInput;
QLineEdit *passwordInput;
QPushButton *loginButton;
void setupUi(QWidget *Login)
{
if (Login->objectName().isEmpty())
Login->setObjectName(QString::fromUtf8("Login"));
Login->resize(1216, 835);
label = new QLabel(Login);
label->setObjectName(QString::fromUtf8("label"));
label->setGeometry(QRect(230, 180, 121, 51));
label->setLineWidth(2);
label_2 = new QLabel(Login);
label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setGeometry(QRect(220, 340, 111, 41));
usernameInput = new QLineEdit(Login);
usernameInput->setObjectName(QString::fromUtf8("usernameInput"));
usernameInput->setGeometry(QRect(490, 190, 141, 51));
passwordInput = new QLineEdit(Login);
passwordInput->setObjectName(QString::fromUtf8("passwordInput"));
passwordInput->setGeometry(QRect(490, 360, 151, 41));
loginButton = new QPushButton(Login);
loginButton->setObjectName(QString::fromUtf8("loginButton"));
loginButton->setGeometry(QRect(520, 480, 88, 34));
retranslateUi(Login);
QObject::connect(loginButton, &QPushButton::clicked, loginButton, qOverload<>(&QPushButton::click));
QMetaObject::connectSlotsByName(Login);
} // setupUi
void retranslateUi(QWidget *Login)
{
Login->setWindowTitle(QCoreApplication::translate("Login", "Login", nullptr));
label->setText(QCoreApplication::translate("Login", "Username:", nullptr));
label_2->setText(QCoreApplication::translate("Login", "Password:", nullptr));
loginButton->setText(QCoreApplication::translate("Login", "Login", nullptr));
} // retranslateUi
};
namespace Ui {
class Login: public Ui_Login {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_LOGIN_H
I'd like to process the stream of my webcam frame by frame with QT6. I've checked the internet but since QTMultimedia was heavily reworked with QT6, and since QT6 is pretty new, all the documentation/questions available are outdated.
So, In order to achieve my goal, I'm using a QMediaCaptureSession with a camera set on QMediaDevices::defaultVideoInput(). I checked that this was working by setting the video output of the QMediaCaptureSession to a QVideoWidget with m_session.setVideoOutput(ui->videowidget);, and it's working fine, except that I can't process the frames (basically, it's rendering my webcam on the QVideoWidget).
Now, to process the frames, I have to use a QVideoSink as far as I understand the documentation here and there. So I replaced m_session.setVideoOutput(ui->videowidget); with m_session.setVideoSink(&mysink);, where mysink is a QVideoSink.
Then, since I want to process the frames, I'm connecting the videoFrameChanged signal of mysink to a function processVideoFrame where I want to do 2 things :
process the current frame
render the result on the UI, ideally on ui->videowidget
This is the point where I'm struggling. I do not understand how to use the paint function of the class QVideoFrame to render the processed frame on the QVideoWidget. More precisely :
I do not understand how I'm supposed to instantiate the QPainter. I tried a straightforward new QPainter(ui->videowidget) but it ends up in a QWidget::paintEngine: Should no longer be called exception and nothing is rendered
I do not understand what is actually representing the second parameter rect of QVideoFrame::paint?
I made a MWE, code is below.
mwe_videosinkpainting.h
#ifndef MWE_VIDEOSINKPAINTING_H
#define MWE_VIDEOSINKPAINTING_H
#include <QMainWindow>
#include <QMediaCaptureSession>
#include <QMediaDevices>
#include <QCamera>
#include <QVideoSink>
#include <QPainter>
QT_BEGIN_NAMESPACE
namespace Ui { class MWE_VideoSinkPainting; }
QT_END_NAMESPACE
class MWE_VideoSinkPainting : public QMainWindow
{
Q_OBJECT
public:
MWE_VideoSinkPainting(QWidget *parent = nullptr);
~MWE_VideoSinkPainting();
private slots:
void processVideoFrame();
private:
Ui::MWE_VideoSinkPainting *ui;
QVideoSink mysink;
QMediaCaptureSession m_session;
QScopedPointer<QCamera> m_camera;
};
#endif // MWE_VIDEOSINKPAINTING_H
mwe_videosinking.cpp
#include "mwe_videosinkpainting.h"
#include "ui_mwe_videosinkpainting.h"
MWE_VideoSinkPainting::MWE_VideoSinkPainting(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MWE_VideoSinkPainting)
{
ui->setupUi(this);
m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
//m_session.setVideoOutput(ui->videowidget);
connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);
m_session.setVideoSink(&mysink);
m_camera->start();
}
MWE_VideoSinkPainting::~MWE_VideoSinkPainting()
{
delete ui;
}
void MWE_VideoSinkPainting::processVideoFrame()
{
QVideoFrame videoframe = mysink.videoFrame();
if(videoframe.map(QVideoFrame::ReadOnly))
{
//This is the part I'm struggling to understand and achieve
videoframe.paint(new QPainter(ui->videowidget), QRectF(0.0f,0.0f,100.0f,100.0f), QVideoFrame::PaintOptions());
videoframe.unmap();
}
}
main.cpp
#include "mwe_videosinkpainting.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MWE_VideoSinkPainting w;
w.show();
return a.exec();
}
ui_mwe_videosinkpainting.h (just so that you have the whole code, it has no value for the question)
#ifndef UI_MWE_VIDEOSINKPAINTING_H
#define UI_MWE_VIDEOSINKPAINTING_H
#include <QtCore/QVariant>
#include <QtMultimediaWidgets/QVideoWidget>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MWE_VideoSinkPainting
{
public:
QWidget *centralwidget;
QGridLayout *gridLayout;
QVideoWidget *videowidget;
QHBoxLayout *horizontalLayout;
QMenuBar *menubar;
QStatusBar *statusbar;
void setupUi(QMainWindow *MWE_VideoSinkPainting)
{
if (MWE_VideoSinkPainting->objectName().isEmpty())
MWE_VideoSinkPainting->setObjectName(QString::fromUtf8("MWE_VideoSinkPainting"));
MWE_VideoSinkPainting->resize(800, 600);
centralwidget = new QWidget(MWE_VideoSinkPainting);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
gridLayout = new QGridLayout(centralwidget);
gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
videowidget = new QVideoWidget(centralwidget);
videowidget->setObjectName(QString::fromUtf8("videowidget"));
horizontalLayout = new QHBoxLayout(videowidget);
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
gridLayout->addWidget(videowidget, 0, 0, 1, 1);
MWE_VideoSinkPainting->setCentralWidget(centralwidget);
menubar = new QMenuBar(MWE_VideoSinkPainting);
menubar->setObjectName(QString::fromUtf8("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 21));
MWE_VideoSinkPainting->setMenuBar(menubar);
statusbar = new QStatusBar(MWE_VideoSinkPainting);
statusbar->setObjectName(QString::fromUtf8("statusbar"));
MWE_VideoSinkPainting->setStatusBar(statusbar);
retranslateUi(MWE_VideoSinkPainting);
QMetaObject::connectSlotsByName(MWE_VideoSinkPainting);
} // setupUi
void retranslateUi(QMainWindow *MWE_VideoSinkPainting)
{
MWE_VideoSinkPainting->setWindowTitle(QCoreApplication::translate("MWE_VideoSinkPainting", "MWE_VideoSinkPainting", nullptr));
} // retranslateUi
};
namespace Ui {
class MWE_VideoSinkPainting: public Ui_MWE_VideoSinkPainting {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MWE_VIDEOSINKPAINTING_H
The answer is quite straightforward : you can use setVideoSink AND setVideoOutput.
The code I gave in OP is good, you just have to uncomment setVideoOutput(ui->videowidget); of mwe_videosinking.cpp and to call setVideoSink BEFORE calling setVideoOutput
Since I cannot format code in a comment...
So, you mean change this...
ui->setupUi(this);
m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
//m_session.setVideoOutput(ui->videowidget);
connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);
m_session.setVideoSink(&mysink);
m_camera->start();
...to this?
ui->setupUi(this);
m_camera.reset(new QCamera(QMediaDevices::defaultVideoInput()));
m_session.setCamera(m_camera.data());
m_session.setVideoSink(&mysink);
m_session.setVideoOutput(ui->videowidget);
connect(&mysink, &QVideoSink::videoFrameChanged, this, &MWE_VideoSinkPainting::processVideoFrame);
m_camera->start();
I did this and I am still only getting black in my videoWidget.
I am following this book and it builds some kind of todo GUI app. We firstly create a MainWindow class:
// MainWindow.hpp
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QMainWindow>
#include <QVector>
#include "Task.hpp" // <- irrelevant to my question
namespace Ui {
class MainWindow;
}
class MainWindow
: public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void add_task();
private:
Ui::MainWindow *ui; // <- this is what I am having problems with
QVector<Task*> m_tasks_vec;
};
#endif // MAINWINDOW_HPP
In the UI designer we add a couple of widgets and one is called tasks_layout:
Then we go on defining members of MainWindow:
// MainWindow.cpp
#include "MainWindow.hpp"
#include "ui_MainWindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_tasks_vec()
{
ui->setupUi(this);
connect(ui->add_task_button, &QPushButton::clicked, this, &MainWindow::add_task);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::add_task()
{
qDebug() << "User clicked on the button!";
auto default_task_name = "Untitled task";
auto *task = new Task(default_task_name);
m_tasks_vec.append(task);
ui->tasks_layout->addWidget(task); // problem here
}
ui->tasks_layout->addWidget(task); part causes the problem:
no member named 'tasks_layout' in 'Ui::MainWindow'
Looking at the picture above, it seems that tasks_layout maybe nested inside centralWidget, so I thought it might be typo in the book and tried ui->centralWidget->tasks_layout->addWidget(task);, but it didn't fix anything:
no member named 'tasks_layout' in 'QWidget'
What am I doing wrong?
The closest thing to my question I found is this, and it didn't help me
This is the auto-generated ui_MainWindow.h:
/********************************************************************************
** Form generated from reading UI file 'MainWindow.ui'
**
** Created by: Qt User Interface Compiler version 5.12.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QToolBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QWidget *centralWidget;
QLabel *status_label;
QPushButton *add_task_button;
QMenuBar *menuBar;
QToolBar *mainToolBar;
QStatusBar *statusBar;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
MainWindow->resize(420, 361);
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
status_label = new QLabel(centralWidget);
status_label->setObjectName(QString::fromUtf8("status_label"));
status_label->setGeometry(QRect(10, 10, 111, 21));
add_task_button = new QPushButton(centralWidget);
add_task_button->setObjectName(QString::fromUtf8("add_task_button"));
add_task_button->setGeometry(QRect(320, 10, 80, 21));
MainWindow->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindow);
menuBar->setObjectName(QString::fromUtf8("menuBar"));
menuBar->setGeometry(QRect(0, 0, 420, 20));
MainWindow->setMenuBar(menuBar);
mainToolBar = new QToolBar(MainWindow);
mainToolBar->setObjectName(QString::fromUtf8("mainToolBar"));
MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar);
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QString::fromUtf8("statusBar"));
MainWindow->setStatusBar(statusBar);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
status_label->setText(QApplication::translate("MainWindow", "Status: 0 todo / 0 done", nullptr));
add_task_button->setText(QApplication::translate("MainWindow", "Add task", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H
Your build system hasn't updated ui_MainWindow.h following changes to MainWindow.ui, it's also lacking the spacers. You need to ensure that it re-runs uic.
That should be done by QCreator's build action, but if it has gotten confused you may have to clean and/or rebuild.
How can I add some action to the QMenuBar outside of window constructor?
I have got some ui_menu.h file created in QtDesigner with QMenuBar:
#ifndef UI_MENU_H
#define UI_MENU_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QAction *actionTtt;
QWidget *centralwidget;
QMenuBar *menubar;
QMenu *menuViev;
QStatusBar *statusbar;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QStringLiteral("MainWindow"));
MainWindow->resize(800, 600);
actionTtt = new QAction(MainWindow);
actionTtt->setObjectName(QStringLiteral("actionTtt"));
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QStringLiteral("centralwidget"));
MainWindow->setCentralWidget(centralwidget);
menubar = new QMenuBar(MainWindow);
menubar->setObjectName(QStringLiteral("menubar"));
menubar->setGeometry(QRect(0, 0, 800, 21));
menuViev = new QMenu(menubar);
menuViev->setObjectName(QStringLiteral("menuFile"));
MainWindow->setMenuBar(menubar);
statusbar = new QStatusBar(MainWindow);
statusbar->setObjectName(QStringLiteral("statusbar"));
MainWindow->setStatusBar(statusbar);
menubar->addAction(menuFile->menuAction());
menuViev->addAction(actionTtt);
retranslateUi(MainWindow);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MENU_H
and in menu.cpp create class of that window:
Menu::Menu(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
In this class I need a function that will add QAction to the QMenuBar
void Menu::AddSubMenu()
{
actionFirst = new QAction(this);
actionFirst->setObjectName("actionFirst");
menuBar->addAction(menuViev->menuAction());
menuViev->addAction(actionFirst);
}
But it shows exeption about: Access violation reading at...
If you created menu "Viev" in menuBar usnig QtDesigner then you do not need this line:
ui->menuBar->addAction(ui->menuView->menuAction());
This code works for me:
void Menu::AddSubMenu()
{
QAction *actionFirst = new QAction(this);
actionFirst->setObjectName("actionFirst");
actionFirst->setText("Test");
ui->menuView->addAction(actionFirst);
}
To help other people understand what is ui. It is Class declareted in menu.h:
#include "ui_menu.h"
class Menu: public QMainWindow
{
Q_OBJECT
public:
....
private:
Ui::MainWindow ui;
Hello I have created an application using qt and I managed to save some of its settings using QSettings.
void DoneIt::writeSettings()
{
QSettings settings("mycompany", "RightDoneIt");
settings.beginGroup("DoneIt");
settings.setValue("size", size());
settings.setValue("pos", pos());
settings.endGroup();
}
void DoneIt::readSettings()
{
QSettings settings("mycompany", "RightDoneIt");
settings.beginGroup("DoneIT");
resize(settings.value("size", QSize(400, 400)).toSize());
move(settings.value("pos", QPoint(200, 200)).toPoint());
settings.endGroup();
}
That works fine with the window position and size.
I have add some widgets in my application using the designer of qt and I would like to save their state too.
One of my widgets is a radio button and I call it radioButtonbnw
How can I save its state (checked or unchecked) ?
What are the best practises ?
Put them to QButtonGroup.
Use QButtonGroup::setId to set Id for each radio button in this group.
Save the Id of the checked button get by QButtonGroup::checkedId.
Get the pointer of this button using QButtonGroup::button(id) when restore, and call QAbstractButton::setChecked.
BTW: if you want to saves the current state of mainwindow's toolbars and dockwidgets, use QMainWindow::saveState.
Here an example widget with three QRadioButton
settingspane.h
#ifndef SETTINGSPANE_H
#define SETTINGSPANE_H
#include <QWidget>
#include <QSettings>
class SettingsPane
: public QWidget
{
Q_OBJECT
QSettings *settings;
public:
explicit SettingsPane(QWidget *parent = nullptr);
public slots:
void handle_rb_buttonReleased(int id);
};
#endif // SETTINGSPANE_H
settingspane.cpp
#include "settingspane.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QRadioButton>
#include <QButtonGroup>
SettingsPane::SettingsPane(QWidget *parent)
: QWidget(parent)
{
settings = new QSettings();
auto mlayout = new QVBoxLayout();
setLayout(mlayout);
// create some buttons
auto rb_frst = new QRadioButton("first");
auto rb_scnd = new QRadioButton("second");
auto rb_thrd = new QRadioButton("third");
// container to organize groups of buttons (no visual)
auto buttonGroup = new QButtonGroup();
buttonGroup->addButton(rb_frst,0);
buttonGroup->addButton(rb_scnd,1);
buttonGroup->addButton(rb_thrd,2);
// layout buttons for visual representation
auto rb_layout = new QHBoxLayout();
rb_layout->addWidget(rb_frst);
rb_layout->addWidget(rb_scnd);
rb_layout->addWidget(rb_thrd);
mlayout->addLayout(rb_layout);
// use Functor-Based Connection due to overloaded buttonReleased
connect( buttonGroup,
SIGNAL(buttonReleased(int)),
this,
SLOT(handle_rb_buttonReleased(int)));
// restore button from settings
int id = settings->value("buttonGroup").toInt();
buttonGroup->button(id)->setChecked(true);
}
void
SettingsPane::handle_rb_buttonReleased(int id)
{
// save new status to the settings
settings->setValue("buttonGroup", id);
}
Using this in a MainWindow
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow
: public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "settingspane.h"
#include <QTabWidget>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
auto cwidget = new QTabWidget();
setCentralWidget(cwidget);
auto settingsPane = new SettingsPane();
cwidget->addTab(settingsPane,"Settings");
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
results in: