How to connect two different objects - c++

I have two objects, one will hold the graph, and the other a few buttons. How to use (connect) so that when you press button 1, the inscription is displayed in debag or the schedule is filled with a new one?
For example, I press the button created by the class BtnBox and my graph is displayed. How to use connect()?
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QThread>
#include "btnbox.h"
#include "plot.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
BtnBox *panel = new BtnBox(&a);
Plot *plot = new Plot();
QObject::connect(panel, SIGNAL(clickedBtn1()), plot, SLOT(slotPrinter()));
// panel->show();
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(plot);
mainLayout->addWidget(panel);
QWidget window;
window.setLayout(mainLayout);
window.show();
return a.exec();
}

Maybe you can use the QPushButton::clicked signal and write something like this:
connect(ui->pushButtonObj, &QPushButton::clicked, plot, &Plot::slotPrinter);
But if you want a custom behavior with your class BtnBox you can create on header file of BtnBox a signal.
signals:
void clickedBtn1();
And use: emit clickedBtn1(); whenever you want to emit it, your connect should work.
There is no need for implementation of the signal, you just have to emit it.
The emit keyword is not really necessary, if you want you can simply use clickedBtn();

Ok, I assume you have class BtnBox, and it already has this in the class definition (in .h file usually):
signals:
void clickedBtn1();
Qt moc will generate the implementation of that method, you don't need to do anything more for it here. But you do need to get that signal emitted. In many cases you would add emit clickedBtn1(); in the right places, but in this case you probably want to do something like this in BtnBox::BtnBox constructor:
connect(ui->button1, SIGNAL(clicked()), this, SIGNAL(clickedBtn1()));
Connecting signal to signal will simply do signal forwarding. Replace ui->button1 with the correct pointer to the button, whatever you have in your code.
Note on how to not do it, just to provide a bit of food for thought: Alternative way would be to expose the button 1 from the class, so in your main() you could then do something like this: QObject::connect(panel->getButton1(), SIGNAL(clickedBtn1()), plot, SLOT(slotPrinter()));. But this is generally considered a bit dirty, exposing internals of BtnBox class like that. It's better to expose the signal, and then the code using the class does not need to care how it gets emitted (for example from several different parts of BtnBox), or how internal implementation of BtnBox might change (for example converting it to QML).

Related

Qt generate UI based on template

I'm looking to generate a set of labels and buttons based on some kind of template, but I don't know how to do the template part.
I'll be using a tab widget which I already have set up, and in one the tabs, I want to have a two labels, a custom button, and a textbox. It'll be repeated around 40-50 times (dependent on a given value at startup) and have spacing as needed.
Once I have a template, I foresee calling it in a loop and setting the appropriate displayed text(Label_1, Label_2, etc) and connect statements where needed.
As I said, I don't know how to template parts of the UI so they can be placed in a kind of auto-generation.
I had thought of making one group, copying the xml, and somehow adding it but that doesn't seem to be a proper way. A little new to Qt.
This is roughly the layout I want to repeat. It has two labels, a lineedit, and one pushbutton.
There's no "good" way to do this in QtDesigner/QtCreator. At best you could copy/paste the set of controls 50 times and then in C++ code hide the ones you don't need. But I wouldn't recommend this.
Instead, just create the controls (labels/button/text box), and a layout to hold them, in C++ code, inside a loop which iterates however many times you need at runtime. Insert the controls layout into the tab widget page layout which you have set up in designer mode. It is not difficult, and will actually be more efficient than what QtDesigner produces since that tends to generate more code than you typically need in the first place.
As a starting point, you could look at the C++ code which is generated by the Qt UI Compiler (UIC) tool for your current design (it takes the XML from designer and turns it into C++ code). You can find this in the build folder for your project, typically named something like ui_ClassName.h, probably in a ui subfolder of the build tree.
UPDATE:
Another, possibly better, way to do this is to create the "template" QWidget class/form, which is going to be used multiple times, as a separate object. The "template" design could be created/maintained using QtCreator/Designer (or just directly in C++). The (possible) advantage here is that as the app requirements evolve, the template widget can be expanded with additional functionality or even re-used in other parts of the UI.
For example, I'd assume the text editor and button in the given mockup image will actually need to do something (eg. edit data and submit it). So some basic functionality can be built into the "template" widget, for example to emit a signal with the text contents of the line editor when the button is pressed.
I put together a quick example. I'm creating the simple MainWindow in pure C++ to simplify/shorten the example code. The "template" I'm calling an Editor. The Editor class and UI form I initially created with the QtCreator wizard (New -> Qt Designer Form Class). I then added the label/control widgets in designer mode. And in C++, a textEdited(const QString &text) signal in the header, and in the Editor() constructor a lambda connection to emit that signal when the button is pressed.
The Editor class code is straight out of the QtCreator wizard except for two edits I'm highlighting below. The designer form has two relevant controls: a QLineEdit (lineEdit) and a QPushButton (pushButton). I'll link to the full files below.
Editor.h
// in the Editor class declarations:
signals:
void textEdited(const QString &text) const;
Editor.cpp
// in the constructor, after ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, [this]() {
emit textEdited(ui->lineEdit->text());
});
Test harness, including MainWindow subclass and main()
#include <QApplication>
#include <QMainWindow>
#include <QTabWidget>
#include <QBoxLayout>
#include <QMessageBox>
#include "Editor.h"
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow() : QMainWindow()
{
// set up a tab widget as the window central widget
QTabWidget *tabWidget = new QTabWidget(this);
setCentralWidget(tabWidget);
// the first/only page will contain all the editors in a vertical layout
QWidget *editorsPage = new QWidget(this);
editorsPage->setLayout(new QVBoxLayout());
// add the editors container page to tab widget
tabWidget->addTab(editorsPage, tr("Editors page"));
// Now create a number of editor widgets using our Editor class "template"
int layoutItems = 5; // number of editors needed, could be dynamic
for (int i=0; i < layoutItems; ++i) {
// Create an Editor instance with the tab page as parent
Editor *editor = new Editor(editorsPage);
// Add the editor widget to the tab page layout
editorsPage->layout()->addWidget(editor);
// A simple connection with the editor signal, as way of example.
connect(editor, &Editor::textEdited, this, [this](const QString &text) {
// just show a message box with the editor text
QMessageBox::information(this, tr("Text Edited"), text, QMessageBox::Ok);
});
}
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
#include "main.moc"
Links The full Editor code:
Editor.h
Editor.cpp
Editor.ui
The XML in Qt Creator is for UIC in QMake to generator code for you.
For example, QMake translates your mainwindow.ui to ui_mainwindow.h, and within you will find void setupUi(QMainWindow *MainWindow) with the actual code that creates and places the widgets.
Look at this code, the docs, and create and place the widgets yourself by code.
For example, adding 5 checkboxes to a groupbox by code:
QVBoxLayout *l = new QVBoxLayout(this);
ui->groupBox_4->setLayout(l);
for(int i=0; i<5; i++){
QCheckBox *c = new QCheckBox(this);
l->addWidget(c);
}

How to break up Qt code into separate parts?

So I am currently writing a Qt app, but am fairly new to it and am unsure of how certain things should be designed. As I add more and more code, my MainWindow.cpp is getting large and unruly. I am curious of what is the proper way to separate my code up in to smaller files. Each of the components that I wish to move to a separate file is making changes to the UI. What I am currently doing is literally just creating a new .cpp file, and then including my MainWindow and also the MainWindow ui. Here is an example of a function that I placed in its own file.
#include <QDebug>
#include <QString>
#include <QPalette>
#include "master_main_window.h"
#include "ui_master_main_window.h"
#include "cmd_net.h"
#include "cmd.h"
/*
* Send a command/data packet to the host
*/
void MasterMainWindow::sendCommand() {
// Disable some GUI components
ui->con_btn_cmd_disc->setEnabled(false);
ui->con_btn_cmd_rec->setEnabled(false);
ui->cmd_edit->setEnabled(false);
ui->cmd_btn_send->setEnabled(false);
// Send the packet through the open socket
sendCmdPacket(ui->cmd_edit->text().toLocal8Bit().data(), cmdSocket);
// Enable the socket notifier
cmdSockNotifier->setEnabled(true);
qDebug() << "Command sent:"
<< (ui->cmd_edit->text().toLocal8Bit().data())
<< "\nSent Packet";
}
As you can see, I have simply included the "master_main_window.h" and "ui_master_main_window.h" which gives me access to all of the different functions/variables/ui available in the MainWindow class. I am curious if I am doing this the proper way, or if there is a better method to achieve my goal of separating the functions into separate files.
If I'm getting what you're asking correctly, since you're working with pointers here you can simply write other classes in different files and pass your variables in ui to them.
For example, let's say you're ui has these variables in it:
QWidget * leftWidget;
QWidget * centerWidget;
QWidget * rightWidget;
You can write classes who inherit QWidget and give these variables to them, like this:
class leftWidgetClass : public QWidget
{
//your code here
}
and so on...
And then in the constructor of your MainWindow you can do this:
leftWidget = new leftWidgetClass();
rightWidget = new rightWidgetClass();
centerWidget = new centerWidgetClass();
The proper way would be to not using ui namespace and mainwindow methods outside of mainwindow class. You should sublass QWidget or any other classes, which functionality you want to extend, create all the functionality you need (like doImportantStuff()) and include this new class header ( let's call it myWidget) in mainwindow.h. Then you can create those myWidget's in mainwindow, add them to ui (ether through disigner, add QWidget, click promote to , select your class, or by adding to layout manually) and use all of their signals and functionality, that you've created, like:
connect(ui->doWorkButtot(),SIGNAL(clicked()), myWidget, SLOT(doImportantStuff()));`
again, changes to ui you can do via signals and slots mechanism; In myWidget when you feel, you have to change ui somehow, emit a signal and catch it in mainwindow with connect. Example:
myWidget.h:
...
signals:
void needUiChange();
....
public slots:
myWidget::doImportantStuff(){
....
emit needUiChange();
// you can emit signals with params also:
// emit setToolTipText(QString("from signal));
...
and in mainwindow catch signal with connect:
connect(myWidget, SIGNAL(needUiChange(),this,SLOT(updateUI());
// actually you can connect directly to let's say `pushButton`'s slot `hide()`

Can't update Text Edit Text QT

I'm having an issue. My textEditBox doesn't seem to be updating when my Addtext function is called.
Here's my Addtext:
void CTextBox::AddText(QString string, QString spriteString)
{
textBrowser->setText(string + spriteString);
update();
}
Another class then calls the function and it should add text to the textbox but it doesn't.
How do you call CTextBox::AddText()? update() only schedules a paintEvent() for later, when the program returns to the event loop. That means that
you actually need to have an event loop, ie. at some point you need to call qApp->exec();
you need to allow the programm some time to qApp->processEvents() (insert that after update()), if you want any paining done within a blocking while() {...} or something like that.
Edit: Come to think of it, you shouldn't even need to call update() nor processEvents() if your program returns to the event loop some time after AddText, so there really seems to be an issue with the event loop. Post your main.cpp, will you?
Here is a trivial example of what it sounds like you are trying to do. Maybe you can see where your design differs?
Notice: no explicit update() is needed. I think that's a red herring. I think it far more likely that (1) you are somehow calling your AddText method with empty strings, or (2) your real text edit is a different variable, and have somehow created two of them and are updating one that just exists in memory and was never added to a layout. Perhaps the code of your FileLoaderQT would help? (You can edit your question rather than posting in comments.)
#include <QtGui>
int main(int argc, char **argv) {
QApplication app(argc, argv);
QMainWindow w;
QTextEdit *edit = new QTextEdit;
w.setCentralWidget(edit);
edit->setText("Hello world!");
w.show();
edit->append("Hello world again!");
return app.exec();
}

Qt doesn't find QStackedWidgets' slot setCurrentWidget

I am writing a wizard-style application in Qt that uses a QStackedWidget to organize the individual pages of the wizard. Now I want to switch between the pages, which should be possible using the function setCurrentWidget(...):
I have a simple main class that instantiates a QWidget audioconfig. Then, it adds this QWidget to a QStackedWidget pageStack using pageStack.addWidget(&audioconfig);.
Later, I want to connect a certain signal from a different QWidget hub to setCurrentWidget(...) of the QStackedWidget in order to switch the page. However, my compiler remarks that
0Object::connect: No such slot QStackedWidget::setCurrentWidget(audioconfig) in /Users/paperflyer/Development/App/main.cpp:41`
There are two things I don't get here:
there clearly is such a function. You can look it up in the class definition of QStackedWidget. What is going on here?
Why is the first character of the compiler output a '0', while my source code clearly and correctly shows it as 'Q'?
Here is the whole code:
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
QStackedWidget pageStack;
CHub hub; // inherits from CWidget
CAudioConfig audioconfig; // ditto
pageStack.addWidget(&hub);
pageStack.addWidget(&audioconfig);
// connect() is a custom signal of hub
QObject::connect(&hub, SIGNAL(configure()), &pageStack, SLOT(setCurrentWidget(&audioconfig)));
pageStack.setGeometry(100,100,700,500);
pageStack.show();
return app.exec();
}
As always, thank you so much for your help!
QObject::connect(&hub, SIGNAL(configure()), &pageStack, SLOT(setCurrentWidget(&audioconfig)));
When you connect a signal to a signal/slot, you connect a signature. The actual parameters are passed when emitting the signal. The above should probably be setCurrentWidget(QWidget*), but even so it won't work, because the signature for the signal must match the one of the slot.
Note: I think that if the signal has more parameters than the slot it will still work, provided that the first parameters are the same.
Your connect line is wrong. It should be:
// connect() is a custom signal of hub
QObject::connect(
&hub, SIGNAL(configure()),
&pageStack, SLOT(setCurrentWidget(QWidget *))); // <- change here
You connect based on the prototype of the slot and/or signal.

Set QLineEdit focus in Qt

I am having a qt question. I want the QLineEdit widget to have the focus at application startup. Take the following code for example:
#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
#include <QtGui/QPushButton>
#include <QtGui/QLineEdit>
#include <QtGui/QFont>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *window = new QWidget();
window->setWindowIcon(QIcon("qtest16.ico"));
window->setWindowTitle("QtTest");
QHBoxLayout *layout = new QHBoxLayout(window);
// Add some widgets.
QLineEdit *line = new QLineEdit();
QPushButton *hello = new QPushButton(window);
hello->setText("Select all");
hello->resize(150, 25);
hello->setFont(QFont("Droid Sans Mono", 12, QFont::Normal));
// Add the widgets to the layout.
layout->addWidget(line);
layout->addWidget(hello);
line->setFocus();
QObject::connect(hello, SIGNAL(clicked()), line, SLOT(selectAll()));
QObject::connect(line, SIGNAL(returnPressed()), line, SLOT(selectAll()));
window->show();
return app.exec();
}
Why does line->setFocus() sets the focus on the line widget #app startup only if it is placed after laying out the widgets and if used before it's not working?
Keyboard focus is related to widget tab order, and the default tab order is based on the order in which widgets are constructed. Therefore, creating more widgets changes the keyboard focus. That is why you must make the QWidget::setFocus call last.
I would consider using a sub-class of QWidget for your main window that overrides the showEvent virtual function and then sets keyboard focus to the lineEdit. This will have the effect of always giving the lineEdit focus when the window is shown.
Another trick that might work is by using the singleshot timer:
QTimer::singleShot(0, line, SLOT(setFocus()));
Effectively, this invokes the setFocus() slot of the QLineEdit instance right after the event system is "free" to do so, i.e. sometime after the widget is completely constructed.
Perhaps this is an update as the last answer was in 2012 and the OP last edited the question in 2014. They way I got this to work was to change the policy and then set the focus.
line->setFocusPolicy(Qt::StrongFocus);
line->setFocus();
In Qt setFocus() is a slot, you can try other overloaded method which takes a Qt::FocusReason parameter like the line shown below:
line->setFocus(Qt::OtherFocusReason);
You can read about focus reason options in the following link:
http://doc.trolltech.com/4.4/qt.html#FocusReason-enum