Having the hardest time setting up signal and slot macros for variables in main. It is extremely easy to do when the variables are located in classes, but how do you do this when you want to connect a variable in main?
I have two radio buttons in main as follows:
QRadioButton *btn_ledWhite = new QRadioButton;
QRadioButton *btn_ledBlack = new QRadioButton;
I want to pass these buttons to a function that sets their stylesheet. Something like below:
btn_led->setStyleSheet("QRadioButton::indicator::unchecked{background-color:gold;}");
When the user of my application presses btn_start, the white player's LED should light up. Unfortunately, I cannot pass the buttons from main to signal and slot macros. I want something like this:
QObject::connect(btn_start, SIGNAL(clicked()), whiteClock, SLOT(updateLED(btn_ledWhite)));
This is illegal qt syntax, however. Apparently, you cannot pass an argument to a function wrapped in a SLOT macro.
You can do something like:
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));
... but I cannot mix the presentation (GUI) layer, with the business layer (i.e. standard 3-tier architecture model... think MVC). Else I would just stick this button in a class and not worry make this thread.
Does anyone have idea how to connect a variable in main with a signal and slot macro?
You can use a QSignalMapper for this.
You connect your buttons' clicked() signal to the mapper's map() slot, then set the mapping from button to led with the mapper's setMapping function.
Once that's done, connect the mapper's mapped signal to your whiteClock. You might need to adjust your slot function's signature to take a QWidget rather than a QPushButton, but if all you need is to call setStyleSheet, then that's not much of a problem.
This code works. You do need to adjust the function signature as previously mentioned to a QWidget*, instead of a QRadioButton*...but everything else should be the same.
main.cpp
QSignalMapper * signalMapper = new QSignalMapper;
//Start game, start white's clock, turn on white's LED
QObject::connect(btn_start, SIGNAL(clicked()), whiteClock, SLOT(startClock()));
QObject::connect(signalMapper, SIGNAL(mapped(QWidget*)), whiteClock, SLOT(updateLED(QWidget*)));
QObject::connect(btn_start, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(btn_start, btn_ledWhite);
Set the stylesheet in your clock class and you're good to go.
Related
I am practicing some GUI programming. I would like to scroll 2 qtextedit at the same time.
my problem is i could not find the SIGNAL for verticalscrollbarvaluechanged.
connect(ui->textEdit,SIGNAL(....),this,SLOT(scroll());
i have this code for the SLOT
void MainWindow::scroll()
{
ui->textEdit->verticalScrollBar()->valueChanged(ui->textEdit2->verticalScrollBar()->value());
ui->textEdit2->verticalScrollBar()->valueChanged(ui->textEdit->verticalScrollBar()->value());
}
also is there a way to hide the scrollbar? just make it look transparent, but it still there?
thank you
You must not create a new slot, you must use the signal of a scrollbar with the slot of the other and vice versa.
connect(ui->textEdit->verticalScrollBar(), SIGNAL(sliderMoved(int)), ui->textEdit_2->verticalScrollBar(), SLOT(setValue(int)));
connect(ui->textEdit_2->verticalScrollBar(), SIGNAL(sliderMoved(int)), ui->textEdit->verticalScrollBar(), SLOT(setValue(int)));
I have a programm with a QLabel, QTextEdit and a QPushButton.
I want to put the text from LineEdit to Label when I click the button.
I can do that by creating my own slot but can it be done with Qt slots?
I've tried this code but it works not as I want...
this->connect(pushButton ,SIGNAL(clicked()), lineEdit, SIGNAL(textChanged(QString)), Qt::QueuedConnection);
t->connect(lineEdit, SIGNAL(textChanged(QString)) , label ,SLOT(setText(QString)), Qt::DirectConnection);
If you need to force the user to push a QButton for "applying" the text he/she typed in a QTextEdit to a QLabel, maybe you want to check the validity of the inserted text, or use the text to achieve some goal or to store it in a variable for later use... so you need a custom slot or a custom class.
Instead you can connect the signal QTextEdit.textChanged(QString) to the slot QLabel.setText(QString), so everything is typed in the QTextEdit is sent to the QLabel without pushing a button.
But all depends on your aim.
Here's how I would do it:
connect(ui->pushbutton, SIGNAL(clicked()), this, SLOT(slot_pushbutton_clicked()))
And then in the the slot_pushbutton_clicked slot,
ui->label->setText(ui->lineEdit->text)
Hope it helps :)
I know how to call a signal from inside the class where the signal is located: by using emit. But what if I want to call it externally, from the parent object?
The reason why I want to do is is because a given QPushButton is connected to a slot which picks the button that called it by using sender(). Now I want the same functionallity of that slot to be called but not after a manual click in the button, but from within the code itself. Normally I would just programatically call for the slot, but because of the usage of sender(), that way is invalid: calling the slot directly will not give it the id of the button.
So how could I "externally" ask for the object for it to emit one of its signals? That is, how can I make my QPushButton emit its clicked() signal from within the code, not by clicking the button with the mouse?
You cannot emit signal directly from the parent object.
Only the class that defines a signal and its subclasses can emit the signal. (http://qt-project.org/doc/qt-4.8/signalsandslots.html#signals)
You can define a method in your QPushButton emitClicked() where you emit the signal. Then you call emitClicked() on instance of your QPushButton from the code.
The Qt headers contain this interesting line (in qobjectdefs.h):
#define emit
Which means that presence or absence of the emit keyword has no effect on the code, it's only there to make it more obvious to the human reader that you are emitting a signal. That is to say:
emit clicked();
is exactly the same (as far as the C++ compiler is concerned) as
clicked();
Given that, if you want your button to emit its clicked() signal, it's just a matter of doing this:
myButton->clicked();
(although if you wanted to be clever about it, this would work equally well):
emit myButton->clicked();
Seems that Qt Test module is just for this case.
Check out this tutorial on simulating GUI events.
Basically you use QTest::​mouseClick and pass pointer to your push button.
Is there a way curry qt slot? Maybe there is something similar to curryng?
Although it's not possible directly using Qt, some binding/currying is available through LibQxt. For example and from the docs of QxtBoundFunction:
By far, the most common expected use is to provide a parameter to a slot when the
signal doesn't have offer one. Many developers new to Qt try to write code like this:
\code
connect(button, SIGNAL(clicked()), lineEdit, SLOT(setText("Hello, world")));
\endcode
Experienced Qt developers will immediately spot the flaw here. The typical solution
is to create a short, one-line wrapper slot that invokes the desired function. Some
clever developers may even use QSignalMapper to handle slots that only need one
int or QString parameter.
QxtBoundFunction enables the previous connect statement to be written like this:
\code
connect(button, SIGNAL(clicked()), QxtMetaObject::bind(lineEdit,
SLOT(setText(QString)), Q_ARG(QString, "Hello, world!")));
\code
This accomplishes the same result without having to create a new slot, or worse,
an entire object, just to pass a constant value.
Additionally, through the use of the QXT_BIND macro, parameters from the signal
can be rearranged, skipped, or passed alongside constant arguments provided
with the Q_ARG macro. This can be used to provide stateful callbacks to a
generic function, for example.
Many kinds of functions can be bound. The most common binding applies to
Qt signals and slots, but standard C/C++ functions can be bound as well.
Future development may add the ability to bind to C++ member functions,
and developers can make custom QxtBoundFunction subclasses for even more
flexibility if necessary.
Although I have submitted some patches to LibQxt, I haven't used this directly so your mileage may vary.
Binding arguments is not possible using Qt signal/slots. You'll have to use boost::signals and boost::bind instead to achieve such functionality.
You could use QSignalMapper to bind connect some signals to it and then connect it's own signals to target slots with some parameters attached.
// connect signal to mapper
signalMapper = new QSignalMapper(this);
signalMapper->setMapping(button1, QString("param1"));
signalMapper->setMapping(button2, QString("param2"));
connect(button1, SIGNAL(clicked()), signalMapper, SLOT(map()));
connect(button2, SIGNAL(clicked()), signalMapper, SLOT(map()));
// connect mapper signal to slot
connect(signalMapper, SIGNAL(mapped(const QString &)), this, SLOT(originalSlot(const QString &)));
Of course, now we have Qt 5 and the ability to connect signals to arbitrary callable objects:
connect(sender, &MyClass::mySignal, receiver, std::bind(&OtherClass::mySlot, boundArg));
connect(sender, &MyClass::mySignal, receiver, [=] { receiver->mySlot(boundArg); });
Hi I've got a spare moment so decided to look at Qt and how easily I can port my windows applications to Qt.
My only real problem is a couple of controls that will need re-implementing under Qt. I've already handled the basic drawing of the control but my control creates a child scroll bar. The problem is that this scrollbar is created dynamically as part of my new Widget (i.e. m_Scrollbar is a member of the widget). How can I then respond to movement of the scrollbar. Under other circumstances this is easy as I'd just create an on_myscrollbar_sliderMoved function under my protected slots and handle it there. This does however rely on the QScrollBar being called myscrollbar. As I've created the object dynamically (i.e. not through designer) how do I capture this signal?
I'm guessing this is really simple and I'm missing the obvious :)
connect( myScrollbar, SIGNAL( <signal signature>), this, SLOT( <slot signature>));
Call connect after creating the scroll bar (I presume that you need this signal handling immediately after creating the scroll bar).
I assumed myScrollbar is of type QScrollBar* and that the slot is defined as a member in your class.
When myScrollbar is destroyed, the connection is removed (disconnect is called).
See the documentation of QObject::connect and QObject::disconnect methods.
Later edit - to be more concrete, in your code it could be:
myScrollbar = new QScrollBar; // Create the scroll bar
// ... add it to the layout, etc.
// ... and connect the signal to your slot
connect( myScrollbar, SIGNAL( sliderMoved( int)), this, SLOT( handleSliderMoved( int)));
where handleSliderMoved is the slot method of your class.