Connecting buttons to mainwindows slot - qt

I tried to do a bunch of research on how to solve this problem, and everything is slightly different than my situation, or didn't work to fix my problem. I will start off by explaining my main goal. I have a main window with 7 buttons on it(amongst other things), when you hit each button, it closes out the current window and opens up a new window. All the windows will have the same 7 buttons, so you can go between each window. With all windows having the exact same 7 buttons, I wanted to set up a function that each class can call to set up each button and connect to a slot() in my mainwindow.cpp(called setupSubsystemButtons in example below). The actual buttons are being placed there, but they only work when pressed from my mainwindow.cpp....when I press them from a different class nothing happens.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWidgets>
#include <QDialog>
namespace Ui {
class MainWindow;
}
class MainWindow : public QDialog
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
QWidget *window;
void setupSubsystemButtons(QGridLayout *layout);
~MainWindow();
private:
Ui::MainWindow *ui;
QLineEdit *tempValueBox;
QLineEdit *humidityValueBox;
QLineEdit *c02ValueBox;
...
public slots:
void ECSgeneralScreen();
void homeScreen();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ecsgeneralcommand.h"
#include <QtWidgets>
#include <QtCore>
MainWindow::MainWindow(QWidget *parent) : QDialog(parent)
{
QGridLayout *layout = new QGridLayout;
...
setLayout(layout);
}
void MainWindow::ECSgeneralScreen()
{
ECSgeneralCommand *ECSgeneral = new ECSgeneralCommand;
this->close();
ECSgeneral->show();
//opens up the ECS screen
}
void MainWindow::homeScreen()
{
MainWindow *home = new MainWindow;
this->close();
home->show();
//opens up the home screen
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setupSubsystemButtons(QGridLayout *layout)
{
//Push Button Layout
homeScreenButton = new QPushButton("Home");
layout->addWidget(homeScreenButton, 3, 11);
connect(homeScreenButton, SIGNAL(clicked()), this, SLOT(homeScreen()));
ECSgeneralScreenButton = new QPushButton("General");
layout->addWidget(ECSgeneralScreenButton,5,11);
connect(ECSgeneralScreenButton, SIGNAL(clicked()), this, SLOT(ECSgeneralScreen()));
}
ecsgeneralcommand.h
#ifndef ECSGENERALCOMMAND_H
#define ECSGENERALCOMMAND_H
#include <QDialog>
#include <QMainWindow>
#include <QtWidgets>
#include <QObject>
#include "mainwindow.h"
class ECSgeneralCommand : public QDialog
{
Q_OBJECT
public:
explicit ECSgeneralCommand(MainWindow *parent = 0);
private:
...
public slots:
};
#endif // ECSGENERALCOMMAND_H
ecsgeneralcommand.cpp
#include "ecsgeneralcommand.h"
#include "mainwindow.h"
#include <QtWidgets>
#include <QtCore>
ECSgeneralCommand::ECSgeneralCommand(MainWindow *parent) : QDialog(parent)
{
QGridLayout *layout = new QGridLayout;
QWidget::setFixedHeight(600);
QWidget::setFixedWidth(550);
...
MainWindow setupButtons;
//Setup Subsystem Buttons
setupButtons.setupSubsystemButtons(layout);
setLayout(layout);
};

MainWindow setupButtons;
//Setup Subsystem Buttons
setupButtons.setupSubsystemButtons(layout);
This will create the buttons and connect their signals to slots of setupButtons, which will get deleted as soon as it's out of scope (the end of the ECSgeneralCommand constructor). So your buttons will be left connected to nothing.
You need to connect the button signals to an object that will exist at the time the button is pressed, such as the ECSgeneralCommand itself. Then it could close itself and spawn the correct window.
Or, possibly a much better solution, if applicable for your application: Use a single main window, with a QStackedWidget that switches widgets when a button is pressed. That's what's typically done.

Related

QWidget-Method hide() destroys surface in IVI-enabled Wayland-Compositor

I have a compositor based on the IVI compositor example in which I can manipulate visibility of surfaces via the "visible" property of the respective surface.
However, when a client tries to hide a QWidget via the hide() method, the compositor will destroy the surface instead of just setting the visible property to false.
Is this the intended behavior, and if so, is there a way to change that?
Steps to reproduce:
Build and run the compositor example
Create a new Qt Widgets Project in QtCreator, leave all settings at default
Change mainwindow.h and mainwindow.cpp to look like this:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QTimer *pTimer;
private slots:
void hideWindow();
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
pTimer = new QTimer();
pTimer->setInterval(1000);
connect(pTimer, SIGNAL(timeout()), this, SLOT(hideWindow()));
pTimer->start();
}
void MainWindow::hideWindow()
{
if (isVisible())
{
qDebug() << "hide!";
hide();
}
else
{
qDebug() << "show!";
show();
}
}
MainWindow::~MainWindow()
{
delete ui;
}
When you build and run this program, it will periodically hide and show its mainwindow, but the way it does this is not by telling the compositor to set the "visible" property of the widget, and instead destroying and re-creating the surface.
Also note that you need to set some environment variables before starting the app:
To start a Qt application using the ivi-application protocol with the right id, you need to set QT_WAYLAND_SHELL_INTEGRATION to ivi-shell and QT_IVI_SURFACE_ID to 1337

Slot is not detected when QPushbutton is released [duplicate]

This question already has answers here:
QObject connection function
(3 answers)
Closed 4 years ago.
I am currently making a main menu for a game, but when the button is clicked it does not seem to call the relevant slot (The button does not do anything). I have tried to move the button to a thread to ensure that nothing is keeping it from running immediately. I have written a simpler program where the button works, so it would seem the problem is not with the button or signal itself. Therefore it must be something keeping it from running?
The source file is given as:
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QObject>
#include <QBrush>
#include"game.h"
#include <QMediaPlayer>
#include <QImage>
#include<QGraphicsPixmapItem>
#include <QPixmap>
#include<QGraphicsItem>
#include <QPushButton>
#include <QLineEdit>
#include <QPalette>
#include <QMessageBox>
#include <QLabel>
#include <QComboBox>
Game::Game(QWidget*parent)
{
//adding the background
QGraphicsScene *scene=new QGraphicsScene();//to create a new graphics scene
scene->setSceneRect( 0,0,1366,768);
setBackgroundBrush(QBrush(QImage(":/images/Back_1_withlogo.jpg")));
setScene(scene);
show();
setFixedSize(1366,768);
//adding logo
//setPixmap(QPixmap(":/images/Logo.png"));
//adding the soundtrack
music=new QMediaPlayer();
music->moveToThread(&MusicThread);
music->setMedia(QUrl("qrc:/sounds/Surreal-Game-Menu.mp3"));
music->play();
MusicThread.start();
//add GUI
this->setFixedSize(1366,768);
this->move(-7,-5);
//start button and username edit box
btnStart = new QPushButton(this);
btnStart->moveToThread(&btnThread);
UserName = new QLineEdit(this);
UserName->setFixedSize(100,25);
UserName->move(300,300);
UserName->show();
UserName->setMaxLength(12);
btnStart->setText("Start");
btnStart->setFixedSize(100,30);
btnStart->show();
btnStart->move(300,600);
connect(btnStart, SIGNAL (released()),this, SLOT (btnStart_clicked()));
btnThread.start();
//label for username edit box
QLabel *LblUsername= new QLabel(this);
LblUsername->setStyleSheet("QLabel { color : white; }");
LblUsername->setFixedSize(100,30);
LblUsername->move(230,300);
LblUsername->setText("Username:");
LblUsername->show();
QLabel *lblGameMode = new QLabel(this);
lblGameMode->setStyleSheet("QLabel { color : white; }");
lblGameMode->setFixedSize(100,30);
lblGameMode->move(190,450);
lblGameMode->setText("Select Game mode:");
lblGameMode->show();
//combobox to select players
GameMode=new QComboBox(this);
GameMode->move(300,450);
GameMode->setFixedSize(100,30);
QStringList Modelist=(QStringList()<<"singleplayer"<<"co-op"<<"multiplayer (3 players)");
GameMode->addItems(Modelist);
GameMode->show();
}
void Game::btnStart_clicked()
{
if (UserName->text()==NULL)
{
QMessageBox messageBox;
messageBox.critical(0,"Error","Please insert username!");
messageBox.setFixedSize(500,200);
}
else
{
numPlayers = GameMode->currentIndex();
SUsername= UserName->text();
UserName->setText("works");
}
}
And the header code is given as:
#ifndef GAME_H
#define GAME_H
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QMediaPlayer>
#include <QThread>
#include <QComboBox>
class Game:public QGraphicsView
{
public:
Game(QWidget*parent=0);
QGraphicsScene*scene;
private slots:
void btnStart_clicked();
private:
QPushButton *btnStart;
QLineEdit *UserName;
QMediaPlayer *music;
QThread MusicThread;
QString SUsername;
QThread btnThread;
QComboBox *GameMode;
int numPlayers;
};
#endif // GAME_H
I received the following error:
QObject::connect: No such slot QGraphicsView::btnStart_clicked() in game.cpp:57
add a Q_OBJECT macro as shown below:
class Game:public QGraphicsView
{
Q_OBJECT
public:
Game(QWidget*parent=0);
QGraphicsScene*scene;
private slots:
void btnStart_clicked();
private:
QPushButton *btnStart;
QLineEdit *UserName;
QMediaPlayer *music;
QThread MusicThread;
QString SUsername;
QThread btnThread;
QComboBox *GameMode;
int numPlayers;
};
This macro helps compiler to determine that the class is using signals and slots mechanism. Basically it creates a entry of defined signals and slots in MOC (meta object compiler) file.
Go through below link for info:
http://www.bogotobogo.com/Qt/Qt5_Q_OBJECT_Macro_Meta_Object.php
QObject::connect (btnStart, &QPushButton::clicked, this, &Game::btnStart_clicked); might work... if you want to use the release event try overriding virtual void mouseRelease or the eventFilter.
And of course... the Q_OBJECT marco.

Qt Main Window not repainting MDI area

I have an application that have a main window with an MDI area that uses the whole window. When the application is opened it is not maximized. If i open the child window and then close it, the ghost of the window still shows. If i open a another child window and then move it across the MDI area you get copies of the window one on top of each other only in the area where the ghost was.
If i open the main window, then maximize it, open the child and maximize it, this problem disappears. Then a can get the main window to the original size, open and close child windows, move them around and the background is redrawn correctly.
Is there anything that can be done to solve this behavior?
Calling the mdi window:
void PriceAnalysisTool::on_actionImport_triggered()
{
importprocess = new ImportProcess(working, printer, ui->mdiArea);
importprocess->show();
}
And the initial part of the sub window:
ImportProcess::ImportProcess(DataBase *d, QPrinter *p, QWidget *parent) : QMdiSubWindow(parent), ui(new Ui::ImportProcess)
{
ui->setupUi(this);
Test program showing the same behavior:
main window:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include "subwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_actionOpen_Window_triggered();
private:
Ui::MainWindow *ui;
SubWindow *subwindow;
};
#endif // MAINWINDOW_H
main window.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionOpen_Window_triggered()
{
subwindow = new SubWindow(ui->mdiArea);
subwindow->show();
}
subwindo.h
#ifndef SUBWINDOW_H
#define SUBWINDOW_H
#include <QWidget>
#include <QMdiSubWindow>
namespace Ui {
class SubWindow;
}
class SubWindow : public QMdiSubWindow
{
Q_OBJECT
public:
explicit SubWindow(QWidget *parent = 0);
~SubWindow();
private:
Ui::SubWindow *ui;
};
#endif // SUBWINDOW_H
subwindw.cpp
#include "subwindow.h"
#include "ui_subwindow.h"
SubWindow::SubWindow(QWidget *parent) : QMdiSubWindow(parent), ui(new Ui::SubWindow)
{
ui->setupUi(this);
}
SubWindow::~SubWindow()
{
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();
}
the ui for the main window has only has a MDI are and the a menu with a single item that calls the subwindow. The subwindow is a widget that has nothing on it.
{
QSqlQuery query;
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch()));
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch())+"T");
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch())+"S");
query.exec("drop table C"+QString::number(markTime.toSecsSinceEpoch())+"F");
delete ui;
}

Bogus widget in Qt Creator

I'm a Qt newbie, working in Qt Creator 3.1.2 (Ubuntu Linux), Qt 5.3.1.
My program has a form with a button (pushButton) which changes the value of a text field (plainTextEdit) on being pressed. Both pushButton and plainTextEdit have been added in graphical mode. Connection between the button and its slot (on_pushButton_clicked()) has been set up via the graphical interface too.
The problem is, the program produces a bogus plainTextEdit, i.e. a different one, in the upper left corner, where the output goes to, while the "main" one stays clean. The question hence is, how I can avoid it? In general, how should I connect graphical widgets and their counterparts in the code? Here is my program:
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QPlainTextEdit>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QPushButton *pushButton;
QPlainTextEdit *plainTextEdit;
};
#endif // MAINWINDOW_H
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.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
plainTextEdit = new QPlainTextEdit(this);
// whenever I remove the previous line, I get SIGSEGV
setWindowTitle(tr("My test app..."));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
plainTextEdit->setPlainText("Some text here");
}
It's the widget you're creating in your constructor that is "bogus". The widgets you created in the forms editor belong to the Ui::MainWindow, you must not re-create them in your main window.
Remove this from your MainWindow:
QPushButton *pushButton;
QPlainTextEdit *plainTextEdit;
Remove the widget creation from the constructor:
plainTextEdit = new QPlainTextEdit(this);
Change your on_pushButtonClicked member to:
ui->plainTextEdit->setPlainText("Some text here");

Phonon::VideoPlayer Qt 4.8.6

Hi I have a problem with Phonon and a slot, it's me first try with this and I hope you could help me,
#include <QMainWindow>
#include <QWidget>
#include <phonon/VideoPlayer>
#include <phonon/VideoWidget>
#include <phonon/MediaObject>
#include <phonon/MediaSource>
#include <phonon>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QPushButton>
#include <QUrl>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
QPushButton *quit;
QPushButton *addFile;
QWidget *Main;
Phonon::VideoPlayer *player;
public slots:
void startVideo();
};
my header ^
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
Main = new QWidget;
addFile = new QPushButton("Dodaj Plik");
quit = new QPushButton("Zamknij");
player = new Phonon::VideoPlayer(Phonon::VideoCategory, Main);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(addFile);
layout->addWidget(quit);
layout->addWidget(player);
Main->setWindowTitle("Phonon");
Main->setLayout(layout);
Main->setGeometry(550, 312, 640, 480);
Main->show();
QObject::connect(addFile, SIGNAL(clicked()), player, SLOT(startVideo()));
QObject::connect(quit, SIGNAL(clicked()), Main, SLOT(close()));
}
MainWindow::~MainWindow()
{
}
void MainWindow::startVideo()
{
QString file = QFileDialog::getOpenFileName(this, tr("odtworz film"));
player->play(file);
}
source ^
For now application runs without problems but when I click "dodaj plik" nothing happens and debugger says it have no such a slot like startVideo()
Can you help me to figure out?
The problem is that you establish connection like this:
QObject::connect(addFile, SIGNAL(clicked()), player, SLOT(startVideo()));
however your startVideo() slot defined in the MainWindow class. Thus, the correct connection should look like:
connect(addFile, SIGNAL(clicked()), this, SLOT(startVideo()));
The QObject:: prefix is not needed, as the QMainWindow - the base class, already is QObject.

Resources