I am try to, by pressing a button in the main QWidget, to create a new QWidget. In that new created QWidget I want to have a button connected to a slot of the main QWidget.
class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
QObject::connect(all,QPushButton::clicked,[](){
SmallGUI* s=new SmallGUI{};
s->show();
});
}
void something(){
//something
}
and the second class
class SmallGUI1 :
public QWidget
{
public:
SmallGUI(){connection();};
private:
QPushButton* N =new QPushButton;
void connection(){
//to connect N to something()
}
I want to connect N to something() .
Before we start, there are some other problems with you code.
Note that in your second class, the constructor is not named the same as the class, which will cause some... Problems.
You also forgot to put a parent for your buttons (which may thus cause some unexpected results) AND for your Widgets (which is again not a good idea).
So, that being said, let us get to the main topic.
I tend to only put prototypes and declare the attributes in the .h file to make the code clearer, but you may of course adapt it to your needs or to your own programming convention.
There are several ways to do something like this, but the simplest one should look like this :
SmallGUI1.h :
#include "UI.h" //The file in which the class UI is declared
//OR :
//class UI; //If you need to include this file in UI.h
class SmallGUI1 : public QWidget{
Q_OBJECT //Q_OBJECT macro, check the doc for more explainations about it
public:
explicit SmallGUI1(UI *parent = nullptr); //Explicit means that this constructor cannot be used for implicit casts
~SmallGUI1();//Destructor needed because I only put the constructor above
private:
QPushButton* N; //Not very good looking to initialize attributes in the .h in my opinion, but works fine.
}
SmallGUI1.cpp :
SmallGUI1::SmallGUI1(UI *parent) : QWidget(parent){
N = new QPushButton(tr("Some text on the button") , this); //tr to enable translation on this string
//************* If I understood your question correctly, this is what you are looking for *************
connect(N , &QPushButton::clicked , parent , &UI::doSomething); //Select the signal you want
/*
Some code here
*/
show();
}
SmallGUI1::~SmallGUI1(){qDeleteAll(children());}
UI.h :
class UI : public QWidget{
Q_OBJECT
public:
explicit UI(QWidget *parent = nullptr);
~UI();
private:
QPushButton* all;
private slots :
void createSmallGUI1();
void doSomething();
}
UI.cpp :
#include "SmallGUI1.h"
UI::UI(QWidget *parent) : QWidget(parent){
all = new QPushButton(tr("ALL") , this);
connect(all , &QPushButton::clicked , this , &UI::createSmallGUI1);
/*
Some code here
*/
}
UI::~UI(){qDeleteAll(children());}
void UI::createSmallGUI1(){SmallGUI1 *gui = new SmallGUI1(this);}
void UI::doSomething(){
/*
Clever code here
*/
}
You can define the second widget as a child of the main widget to make things easier:
class UI : public QWidget {
...
private:
SmallGUI* s;
...
and then initialize it in the UI constructor, along with your all button. You can initially hide the child widget or disable it:
UI() {
all = new QPushButton{"ALL", this};
setWindowTitle("UI"); // just for clarification
s = new SmallGUI(this);
s->hide();
connection();
};
and 'show' it with button clicked signal
connect(all, &QPushButton::clicked, s, &SmallGUI::show);
Doing so gives you the option to connect the clicked signal of your N button to the something function in the parent class
connect(s->N, &QPushButton::clicked, this, &UI::something);
The complete program would be as follows,
#include <QApplication>
#include <QMessageBox>
#include <QPushButton>
#include <QWidget>
class SmallGUI : public QWidget {
public:
SmallGUI(QWidget* parent) : QWidget(parent) {
N = new QPushButton{"btn2", this};
connection();
};
QPushButton* N;
private:
void connection(){};
};
class UI : public QWidget {
public:
UI() {
all = new QPushButton{"ALL", this};
setWindowTitle("UI"); // just for clarification
s = new SmallGUI(this);
s->hide();
connection();
};
private:
SmallGUI* s;
QPushButton* all;
void connection() {
connect(all, &QPushButton::clicked, s, &SmallGUI::show);
connect(s->N, &QPushButton::clicked, this, &UI::something);
}
void something() { QMessageBox::information(this, "Hello", "Hello"); }
};
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
UI w;
w.show();
return a.exec();
}
It is not good idea to connect to parent's slots from "nested" class, since SmallGUI1 will be tied to class UI.
Here is better solution, I think:
class UI : public QWidget
{
public:
UI(){connection();};
private:
QPushButton* all = new QPushButton{ "ALL" };
void connection(){
QObject::connect(all,QPushButton::clicked,[](){
SmallGUI1* s=new SmallGUI1;
connect(s,&USmallGUI1::button_clicked,this,&UI::something);
s->show();
});
}
void something(){
//something
}
And SmallGUI1 class:
class SmallGUI1 :
public QWidget
{
public:
SmallGUI1(){connection();};
signals:
void button_clicked();
private:
QPushButton* N;
void connection(){
//to connect N to something()
N = new QPushButton;
connect(N,&QPushButton::clicked,this,&SmallGUI1::button_clicked)
}
This way, you are connecting QPusButton::clicked signal from SmallGUI1 to the signal SmallGUI1::button_clicked(). Dont need to implement additional slot, just connect signal to signal.
And in UI you are connecting button_clicked() signal to the slot dosomething()
DONT FORGET THE CONSTRUCTOR OF SmallGUI1! In your code, SmallGUI() will be just a method, which will not be called when SmallGUI1 is instantiated, and you have to call it by yourself.
I googled a lot before writing here. I found a couple of posts but I couldn't quite get them. So I'm starting a new post.
I am developing a simple UI. There is this main class (see below), which is a main dialogue box which is shown when the app is started.
class MainWindow : public QMainWindow
There are few buttons on the MainWindow dialogue box, when I click a button, it hides the MainWindow and opens another QDialog box. This dialogue box is of the class as shown below
class libinsert : public QDialog
I create the libinsert object this way:
void MainWindow::on_pushButton_clicked()
{
this->hide();
libinsert lib; // I create libinsert object this way
lib.setModal(true);
lib.exec();
}
This is libinsert.cpp:
libinsert::libinsert(QWidget *parent) :
QDialog(parent),
ui(new Ui::libinsert)
{
ui->setupUi(this);
}
When the libinsert dialogue box is open, I need to access a socket variable which is a member of class MainWindow. How do I achieve this ?
My main app looks like this:
{
QApplication a(argc, argv);
MainWindow w(sock);
w.show();
return a.exec();
};
Alternatively: in general how are multiple dialogue boxes built, as parent-child relation?
libinsert will not be a child of MainWindow. QDialog-based windows are always top-level windows, regardless of what you pass as their parent when you construct them.
If there will only ever exist a single instance (per process) of MainWindow at any given time, you can give MainWindow a static function which returns a pointer to the window:
class MainWindow : public QMainWindow
{
public:
MainWindow()
{
theWindow = this;
}
virtual ~MainWindow()
{
theWindow = nullptr;
}
static get()
{
return theWindow;
}
static MainWindow *theWindow;
}
MainWindow *MainWindow::theWindow = nullptr;
Your dialogs can then access the main window's members thusly:
MainWindow::get()->someMemberFunction();
A more robust approach is to have libinsert store a pointer to the main window when it is created:
class MainWindow;
class libinsert : public QDialog
{
public:
libinsert(MainWindow *mw)
: mainWindow(mw)
{ ... }
MainWindow *getMainWindow()
{
return mainWindow;
}
MainWindow *mainWindow;
}
When MainWindow creates the dialog, it passes a pointer to itself to the constructor:
void MainWindow::createDialog()
{
libinsert *dialog = new libinsert(this):
}
This approach will work even if there are multiple instances of MainWindow active at the same time.
I trying to display some text to a textbrowser via: FindChild and it never displays it in the textbrowswer any help would be helpfull..
Here is my mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
namespace Ui
{
class MainWindow;
class TestWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
static MainWindow* GetInstance(QWidget* parent = 0);
signals:
public slots:
void on_pushButton_3_clicked();
void MainWindow_TextBrowser_String(const QString & newText);
private:
Ui::MainWindow *ui;
static MainWindow* mainInstance;
};
Here is my mainwindow.cpp
// Constructor
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
// Destructor
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_3_clicked()
{
TestWindow mwindow;
mwindow.start();
}
MainWindow* MainWindow::mainInstance = 0;
MainWindow* MainWindow::GetInstance(QWidget *parent)
{
if (mainInstance == NULL)
{
mainInstance = new MainWindow(parent);
}
return mainInstance;
}
void MainWindow::MainWindow_TextBrowser_String(const QString & newText)
{
QString TextBrowser_String = QString(newText);
ui->textBrowser->append(TextBrowser_String);
}
I create the testwindow object in the pushbutton send the start function to call the findchild window to send a string to the textbrowser window
Here is my testwindow.cpp
void testwindow::start()
{
// Create a new mainwindow on the heap.
MainWindow* instance = MainWindow::GetInstance();
// Or I can call
// MainWindow instance; then point to findchild
QString Test_Window_String = QStringLiteral("Test Window String");
instance->findChild<QTextBrowser*>("textBrowser")->append(Test_Window_String);
}
I understand that you can use a singal and slot and simply just create a signal that sends the string to the append textbrowser
void testwindow::singalandslot()
{
MainWindow* instance = MainWindow::GetInstance();
connect(this, SIGNAL(TextBrowswer_String(const QString &)), instance , SLOT(MainWindow_TextBrowser_String(QString &)));
}
void testwindow::fireSignal()
{
emit TextBrowswer_String("sender is sending to receiver.");
}
Even with a signal or FindChild it seems that the object is already deleted or i'm doing something wrong.
Can you please share your Ui::MainWindow Class and setupUi implementation to get a clear view?
Hope you have created the instance for QTextBrowser* inside setupUi or in the constructor.
With the below setupUi implementation, both ur usecases are working.
namespace Ui
{
class MainWindow: public QWidget
{
Q_OBJECT
public:
QTextBrowser* textBrowser;
void setupUi(QWidget* parent)
{
setParent(parent);
textBrowser = new QTextBrowser(parent);
textBrowser->setObjectName("textBrowser");
textBrowser->setText("Hello");
}
};
}
I have a class which inherits from QDialog (dialog_game_over). I show an object of that class in a slot of another class. I want to close mainwindow and QDialog when user clicked on ok button. First I built an object of mainwindow in dialog_game_over and close it. But this way it wasn't correct. What do I do for closing program in class other than main class?
dilog_game_over::dilog_game_over(QWidget *parent) :
QDialog(parent),x_size(400),y_size(400)
{
ok=new QPushButton(this);
ok->setText("OK");
ok->move(200,200);
connect(ok,SIGNAL(clicked()),this,SLOT(on_ok_clicked()));
}
void dilog_game_over::on_ok_clicked()
{
accept();
this->close();
}
class Myenemy1 : public QGraphicsObject
{
Q_OBJECT
public slots:
void loss();
private:
dilog_game_over dlg;
}
void Myenemy1::loss()
{
....
dlg.exec();
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),size_of_plane_y(600),size_of_plane_x(2500)
{
set_scene();
put_cloud();
put_point();
}
All over your application you can exit by :
qApp->quit();
Or
qApp->exit(0);
I've been searching a lot and I still can't find a good example of how to have multiple windows inside the same application with GTK. My program is in C++ but I don't mind an example in C which would help me understand the principle anyway.
So, the basic idea is to create my own derived object from Gtk::Window as opposed to Gtk::Dialog. Dialog has a run method which works flawlessly to open a modal popup window, but it's not flexible enough for what I'm trying to do. Does anyone know how I'd go about spawning a new window when I click a button in my program?
For example:
void MainWindow::on_button_clicked()
{
NewWindow window;
//Some code to display that window and stay in a loop until told to return
}
Where NewWindow is derived from Gtk::Window as such:
class NewWindow : public Gtk::Window
{
//Normal stuff goes here
}
Anything will help...I'm really confused here!
Another way to have a new window is to create a pointer to a Gtk window variable(Gtk::Window* about_window_;) then set the Gtk window variable to a new instance of the other window (about_window_ = new Window;), after that show the new window (about_window_->show();). Below is a full example of this:
class AboutWindow : public Gtk::Window
{
public:
AboutWindow();
~AboutWindow();
protected:
Gtk::Label lbl_;
};
AboutWindow::AboutWindow()
{
this->set_default_size(100, 100);
this->set_title("About");
lbl_.set_label("About label");
this->add(lbl_);
this->show_all_children();
}
AboutWindow::~AboutWindow()
{
}
class MainWindow : public Gtk::Window
{
public:
MainWindow();
virtual ~MainWindow();
protected:
void onButtonClicked();
void aboutWinClose();
Gtk::Button button_;
Gtk::Label lbl_;
Gtk::Box box_;
Gtk::AboutWindow* aboutw_;
};
MainWindow::MainWindow()
{
this->set_default_size(100, 100);
box_.set_orientation(Gtk::ORIENTATION_VERTICAL);
this->add(box_);
box_.pack_start(lbl_);
lbl_.set_label("a test");
button_.set_label("Open About Window");
box_.pack_end(button_);
button_.signal_clicked().connect(sigc::mem_fun(*this, &MainWindow::onButtonClicked));
aboutw_ = 0;
this->show_all_children();
}
MainWindow::~MainWindow()
{
}
void MainWindow::onButtonClicked()
{
if(aboutw_ != 0)
return;
aboutw_ = new AboutWindow;
aboutw_->signal_hide().connect(sigc::mem_fun(*this, &MainWindow::aboutWinClose));
aboutw_->show();
}
void MainWindow::aboutWinClose()
{
aboutw_ = 0;
}
Added for reference.
If you don't want the new window to be modal, then simply create it, show() it, and return from your main window's method without entering a loop.