Hi Im try to make a custom slot with the h file that qt4 designer generated
I see how the standard slot is made but i would like to, "once past learning this step" have run terminal commands and have it output in the text box so im tryin to replace the past() slot with one i can right commands in
Here is the h file file that works great but.... the above problem'' trying to understand the flow.. 2nd day so any pointers are awsome. so here it is i will comment where i think i should be working.. but have had no success all day lol.
#ifndef SWEETGUIFORMQ19488_H
#define SWEETGUIFORMQ19488_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QHeaderView>
#include <QtGui/QTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
QT_BEGIN_NAMESPACE
class Ui_SweetGuiForm
{
public:
QVBoxLayout *verticalLayout_2;
QVBoxLayout *verticalLayout;
QTextEdit *textEdit;
QDialogButtonBox *buttonBox;
void setupUi(QWidget *SweetGuiForm)
{
if (SweetGuiForm->objectName().isEmpty())
SweetGuiForm->setObjectName(QString::fromUtf8("SweetGuiForm"));
SweetGuiForm->resize(511, 275);
verticalLayout_2 = new QVBoxLayout(SweetGuiForm);
verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
verticalLayout = new QVBoxLayout();
verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
textEdit = new QTextEdit(SweetGuiForm);
textEdit->setObjectName(QString::fromUtf8("textEdit"));
verticalLayout->addWidget(textEdit);
buttonBox = new QDialogButtonBox(SweetGuiForm);
buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
verticalLayout->addWidget(buttonBox);
verticalLayout_2->addLayout(verticalLayout);
QWidget::setTabOrder(textEdit, buttonBox);
retranslateUi(SweetGuiForm);
QObject::connect(buttonBox, SIGNAL(rejected()), SweetGuiForm, SLOT(close()));
ok here i guess i could replace the paste() with on_buttonBox_accepted(), please correct me i really am still quessing at this point but where do i right the function? do i do the in a file called sweetguiform.cpp ? this is where im lost.. help..
QObject::connect(buttonBox, SIGNAL(accepted()), textEdit, SLOT(paste()));
QMetaObject::connectSlotsByName(SweetGuiForm);
} // setupUi
void retranslateUi(QWidget *SweetGuiForm)
{
SweetGuiForm->setWindowTitle(QApplication::translate("SweetGuiForm", "Form", 0, QApplication::UnicodeUTF8));
} // retranslateUi
};
namespace Ui {
class SweetGuiForm: public Ui_SweetGuiForm {};
} // namespace Ui
QT_END_NAMESPACE
#endif // SWEETGUIFORMQ19488_H
Is this the way to do things when brand new?
I think you shouldn't be editing the header file that Qt generates for you. Instead, you should write your own header/implementation file that includes this auto-generated header and sets up the signal-slot connections there. For example:
#include "ui_SweetGuiForm.h"
class SweetGuiForm : public QWidget
{
public:
SweetGuiForm( ): ui( new Ui::SweetGuiForm )
{
ui->setupUi( this );
}
public slots:
void on_buttonBox_accepted( )
{
// your code here
}
protected:
Ui::SweetGuiForm* ui;
};
Qt will find the on_buttonBox_accepted method and set up the signal-slot connection for you, so you don't have to call QObject::connect.
Related
I'm new to any form of programming but have to do a project with Qt for my "programming for engineers" course where we simultaneously learn the basics of c++.
I have to display a text from one lineEdit to a lineEdit in another window.
I have a userWindow that opens from the mainWindow and in this userWindow I have a lineEdit widget that displays the current selected user as a QString (from a QDir object with .dirName() ). But now I have to display the same String in a lineEdit in the mainWindow as well.
From what I've read I have to do this with "connect(...)" which I have done before with widgets inside a single .cpp file but now I need to connect a ui object and signal from one window to another and I'm struggling.
My idea /what I could find in the internet was this:
userWindow.cpp
#include "userwindow.h"
#include "ui_userwindow.h"
#include "mainwindow.h"
#include <QDir>
#include <QMessageBox>
#include <QFileDialog>
#include <QFileInfo>
QDir workingUser; //this is the current selected user. I tried defining it in userWindow.h but that wouldn't work how I needed it to but that's a different issue
userWindow::userWindow(QWidget *parent) : //konstruktor
QDialog(parent),
ui(new Ui::userWindow)
{
ui->setupUi(this);
QObject::connect(ui->outLineEdit, SIGNAL(textChanged()), mainWindow, SLOT(changeText(workingUser) //I get the error " 'mainWIndow' does not refer to a value "
}
[...]
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QDir>
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void changeText(QDir user); //this is the declaration of my custom SLOT (so the relevant bit)
private slots:
void on_userButton_clicked();
void on_settingsButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "userwindow.h"
#include "settingswindow.h"
#include "click_test_target.h"
#include "random_number_generator.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
[...]
}
[...]
//here I define the slot
void MainWindow::changeText(QDir user)
{
QString current = user.dirName();
ui->userLine->insert("The current working directory is: "); //"userLine" is the lineEdit I want to write the text to
ui->userLine->insert(current);
}
I know I'm doing something wrong with the object for the SLOT but can't figure out how to do it correctly.
If anyone could help me I would be very grateful.
Alternatively: perhaps there is another way to mirror the text from one lineEdit to another over multiple windows. If anybody could share a way to do this I would be equally grateful. Is there maybe a way to somehow define the variable "QDir workingUser;" in such a way as to be able to access and overwrite it in all of my .cpp files?
Thank you in advance for any help. Regards,
Alexander M.
"I get the error 'mainWindow' does not refer to a value"
I don't see you having any "mainWindow" named variable anywhere,
but you also mentioned that the MainWindow is the parent, which means you could get reference anytime, like:
MainWindow *mainWindow = qobject_cast<MainWindow *>(this->parent());
Also, your signal-handler (changeText(...) slot) should take QString as parameter (instead of QDir), this way you handle how exactly the conversion is handled, in case users type some random text in input-field (text-edit).
void changeText(const QString &input);
Finally, you either need to specify type:
QObject::connect(ui->outLineEdit, SIGNAL(textChanged(QString)), mainWindow, SLOT(changeText(QString));
Or, use the new Qt-5 syntax:
connect(ui->outLineEdit, &QLineEdit::textChanged,
mainWindow, &MainWindow::changeText);
You can create new signal (same params as lineEdit's textChanged) to userWindow which is connected to the textChanged signal of the lineEdit. Then connect that signal userWindow to mainWindow's slot.
//In userWindow.h
signals:
void textChanged(const QString&);
//In userWindow.cpp
connect(ui.lineEdit, &QLineEdit::textChanged, this, &userWindow::textChanged);
//In mainWindow.cpp
connect(userWindow, &userWindow::textChanged, this, &mainWindow::onTextChanged
Then in onTextChanged write the same text to mainWindow's lineEdit
Before we start things, this could be a possible duplicate of Qt Scroll Area does not add in scroll bars, however the answer provided by the user and which seemed to work for the OP, does not work for me. I fear it may have to do with versions, perhaps? Or am I missing something? (it is possible!)
Alright, for those who know Qt, I am a beginner and I have what seem to be a pretty silly problem, but is giving me a lot of headaches:
I want to press a push button and add items to a container, then it is supposed to be possible to scroll it down. As simple as that.
So I thought that perhaps setting a layout to scrollArea would do the job. It indeed adds my items as I wanted, but it doesn't load the scrollBar. I have checked the ScrollPolicy already, but nothing satisfied my issue. It is like the GVBoxLayout doesn't increase size and doesn`t let the scroll area to scroll.
Does anybody have a clue on how to fix it?
Code below:
saleWindow.h
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include<QString>
namespace Ui {
class SaleWindow;
}
class SaleWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SaleWindow(QWidget *parent = 0);
~SaleWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::SaleWindow *ui;
QVBoxLayout *gBoxLayout;
QMap<QString, QListWidget *> m_mappings;
};
#endif // SALEWINDOW_H
saleWindow.cpp
#include "salewindow.h"
#include "ui_salewindow.h"
#include <iostream>
#include <QGroupBox>
#include <QLabel>
//#include <QtSql/QSqlDatabase>
//#include <QtSql>
#include <QtWidgets/QPushButton>
SaleWindow::SaleWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::SaleWindow),
gBoxLayout(new QVBoxLayout())
{
ui->setupUi(this);
// Adding layout to scrollbar
{
ui->scrollArea_sales->setWidgetResizable(true);
ui->scrollArea_sales->setLayout(gBoxLayout);
QWidget *central = new QWidget;
ui->scrollArea_sales->setWidget(central);
}
}
SaleWindow::~SaleWindow()
{
delete ui;
delete gBoxLayout;
}
void SaleWindow::on_pushButton_clicked()
{
QGroupBox *sale = new QGroupBox();
sale->setTitle("minha venda");
gBoxLayout->addWidget(sale);
ui->scrollArea_sales->setLayout(gBoxLayout);
}
If you are using a QScrollArea for the scrollArea_sales object from the ui editor, you can see in the object inspector(qtdesigner) a default widget in the QScrollArea, so you not need to add this. Try this code:
// Adding layout to scrollbar(on the contrctor, replace yor scope by)
{
ui->scrollArea_sales->widget()->setLayout(gBoxLayout);
}
void MainWindow::on_pushButton_clicked() {// on the slot replace all by:
QGroupBox *sale = new QGroupBox();
sale->setTitle("minha venda");
ui->scrollArea_sales->widget()->layout()->addWidget(sale);
}
I Started learning Qt (5.5) a couple of days ago, and I recently got stuck on something when working with the connect function, specifically the SLOT parameter. I'm calling a member function from the same class that the connect function is called in, but when the SLOT function is triggered it acts like it's creating a new class object. It worked initially when I kept everything in the same class, but this problem popped up when I tried implementing a hierarchy. I wrote a short program to demonstrate my problem.
Main.cpp
#include <QApplication>
#include "MainWindow.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow QtWindow;
QtWindow.show();
return app.exec();
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QGridLayout>
#include "TopWidget.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QMainWindow *parent = 0);
private:
QWidget *mainWidget;
QGridLayout *mainLayout;
};
#endif // MAINWINDOW_H
MainWindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QMainWindow *parent) : QMainWindow(parent){
mainWidget = new QWidget(this);
mainLayout = new QGridLayout(mainWidget);
setCentralWidget(mainWidget);
TopWidget tWidget(this);
mainLayout->addWidget(tWidget.topWidget, 0, 0);
}
TopWidget.h
#ifndef TOPWIDGET_H
#define TOPWIDGET_H
#include <stdlib.h>
#include <QWidget>
#include <QPushButton>
#include <QGridLayout>
#include <QDebug>
#include <QErrorMessage>
class TopWidget : public QWidget
{
Q_OBJECT
public:
TopWidget(QWidget *parent);
QWidget *topWidget;
private:
QGridLayout *wLayout;
QPushButton *Button;
int memVar1;
int memVar2;
private slots:
void testConnect();
//void SlotWithParams(int a, int b);
};
#endif // TOPWIDGET_H
TopWidget.cpp
#include "TopWidget.h"
TopWidget::TopWidget(QWidget *parent) : QWidget(parent){
topWidget = new QWidget(parent);
wLayout = new QGridLayout(topWidget);
memVar1 = 123;
memVar2 = 321;
Button = new QPushButton("Click Me", topWidget);
connect(Button, &QPushButton::clicked, [=](){ TopWidget::testConnect(); });
}
void TopWidget::testConnect(){
qDebug("Button worked");
if(memVar1 != 123 || memVar2 != 321){
qDebug("Linking failed");
}else{
qDebug("Linking success");
}
}
Since I just started with Qt, I don't have a good feel for what's "proper" Qt code, and what I should avoid, so tips in that direction are also appreciated. The following is the qmake file, if that's important.
CONFIG += c++11
CONFIG += debug
CONFIG += console
QT += widgets
QT += testlib
SOURCES += main.cpp
SOURCES += MainWindow.cpp
SOURCES += TopWidget.cpp
HEADERS += MainWindow.h
HEADERS += TopWidget.h
Release:DESTDIR = bin/Release
Release:OBJECTS_DIR = obj/Release
Release:MOC_DIR = extra/Release
Release:RCC_DIR = extra/Release
Release:UI_DIR = extra/Release
Debug:DESTDIR = bin/Debug
Debug:OBJECTS_DIR = obj/Debug
Debug:MOC_DIR = extra/Debug
Debug:RCC_DIR = extra/Debug
Debug:UI_DIR = extra/Debug
When I run the program in debug mode and press the button, it outputs "Button worked" indicating the link to the function was successful, but then outputs "Linking failed" indicating that a new object was created rather than taking the old one. My knowledge of C++ is patchy, since I only pick up what I need to, and I spent hours yesterday trying to fix this, so forgive me if the fix is something ridiculously easy, but I've mentally exhausted myself over this.
The problem comes from this line:
TopWidget tWidget(this);
You are allocating tWidget on the stack, and it gets destroyed just at the end of the MainWindow constructor.
Replace by:
TopWidget * tWidget = new TopWidget(this);
Also, you should replace your connect line by this one
connect(Button, &QPushButton::clicked, this, &TopWidget::testConnect);
It appears that your slot is called even after the TopWidget is destroyed. Qt normally disconnects connections when sender or receiver are destructed, but it's not able to do that when you connect to a lambda.
And finally, you are doing something weird. What is the purpose of your TopWidget class besides just creating another widget and receiving signals on its slot? You never add the TopWidget to any layout, but just its child. TopWidget is never shown, so it should rather derive from QObject only.
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). However, I can't seem to get the window to close using the standard "this->close()"...it works when I go from the main window to another window(the main window closes) but when I go from a different window to say the home window, the different window doesn't close. Suggestions would be greatly appreciated. My guess is that my understanding of "this" when it comes to calling slots in another class is wrong.
mainwindow.cpp( the parts that are relevant)
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 ECS 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()));
}
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 slots:
public slots:
void ECSgeneralScreen();
void homeScreen();
};
#endif // MAINWINDOW_H
ecsgeneralcommandWindow
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(650);
...
//Setup Subsystem Buttons
test.setupSubsystemButtons(layout);
setLayout(layout);
}
ecsgeneralcommandWindow header
#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:
MainWindow test;
public slots:
};
#endif // ECSGENERALCOMMAND_H
Slots are just normal functions. When Qt invokes a slot, it ends up calling the appropriate receiver's method. In other words, this equals to the value of the 3rd argument of your connect statements. You passed this there, so the receiver is MainWindow object. E.g. MainWindow::homeScreen method always tries to close MainWindow. If it is already hidden, this action takes no effect.
You should either have a slot in each window class and connect buttons to appropriate receivers, or use a pointer to the currently active window instead of this when calling close(). But your architecture is strange in the first place. Why would you need to create these buttons for each window? It is reasonable to create them once and use in all windows. Also hiding and showing windows is not necessary. You can create one main window with buttons and a QStackedWidget that will contain the content of all other windows. Maybe you can even use QTabWidget instead of these buttons.
I am having a problem with connect in the program I am currently writing. I first create a "main window" dialog that contains buttons, line edits, etc. (which all work perfectly fine with my custom slots). One of the buttons (the "Add Class" button) should create a new pop up dialog that is a child of the mainWindow dialog. I wrote a new .h and .cpp for this new dialog (addClass.h and addClass.cpp). When I click the button, the dialog modality is set to ApplicationModal and up to this point, the code works; when I click "Add Class" and new dialog shows up as a pop up with all the labels, line edits, and buttons that I want. The problem comes in when I try and use the connect using this new class. Upon clicking the ok button the connect is not executed. The program compiles properly (using qmake and then make) and gives no errors during run time. I also took the .h and .cpp files from the pop up dialog and tested them with their own main.cpp and the connect worked perfectly. I am stumped as to what the problem could be, so any help would be awesome!
Here are some snipets of code that might be helpful:
the custom slot that initiates the pop up dialog in mainWindow.cpp (works and I include "addClass.h" in mainWindow.cpp):
void mainWindow::addClassCombo(){
addClass aC(win);
}
addClass.h:
#ifndef ADDCLASS_H
#define ADDCLASS_H
#include <QDialog>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
class addClass : public QDialog{
Q_OBJECT
public:
addClass(QWidget *parent = 0);
private slots:
void addToTxt();
private:
QDialog *addMathClass;
QVBoxLayout *mainLayout;
QHBoxLayout *layoutOkCanc;
QLabel *nameL; //label for name of math class to be added
QLineEdit *name; //line edit for name
QPushButton *ok; //ok button
QPushButton *canc; //cancel button
};
#endif
addClass.cpp (works with its own main.cpp but not the one with my mainWindow.cpp):
#include <QtGui>
#include <QTextStream>
#include "addClass.h"
#include <iostream>
addClass::addClass(QWidget *parent):QDialog(parent){
addMathClass = new QDialog(parent);
mainLayout = new QVBoxLayout(addMathClass);
layoutOkCanc = new QHBoxLayout();
nameL = new QLabel("Math Class Name:");
name = new QLineEdit;
nameL->setBuddy(name);
ok = new QPushButton("Ok");
canc = new QPushButton("Cancel");
QObject::connect(canc, SIGNAL(clicked()), addMathClass, SLOT(close()) ); //<-works
QObject::connect(ok, SIGNAL(clicked()), this, SLOT(addToTxt()) ); //<-doesn't work
QObject::connect(ok, SIGNAL(clicked()), addMathClass, SLOT(close()) ); //<-works
layoutOkCanc->addStretch();
layoutOkCanc->addWidget(ok);
layoutOkCanc->addWidget(canc);
mainLayout->addWidget(nameL);
mainLayout->addWidget(name);
mainLayout->addLayout(layoutOkCanc);
addMathClass->setWindowModality(Qt::ApplicationModal);
addMathClass->setWindowTitle("Add Class");
addMathClass->show();
}
void addClass::addToTxt(){
std::cout<<"testing"<<std::endl;
}
Your addClass aC(win); goes out of scope and is being destroyed. Connection works, but after object destruction is disconnected. That's why you're not getting slot called