So i'm new into Qt and i'm just testing GUI stuff out, creating windows and widgets, so i want to know if there's a way for me to make a QPushButton disabled until a specific condition is met(until the user inputs their username and password into a QLineEdit widget)...I want that login button to be disabled until the condition is met
Yes absolutely you can. You should define a signal and slot and connect them together. In your slot, enable the login button and where your condition meet trigger the signal by emit yourSignal().
e.g pseudo code:
class header:
signals:
void yourSignal();
private slots:
void onSignalEmitted();
class body:
YourClass::YourClass() {
connect(this, &YourClass::yourSignal, this, &YourClass::onSignalEmitted);
}
void YourClass::onSignalEmitted() {
ui->login_button.enable();
}
Don't forget to emit your signal when condition meet like this:
emit yourSignal();
Related
I am creating an app using QtCreator 4.12 and am using a touch screen for input. I want a virtual keyboard to pop up when any QLineEdit is in focus and the keyboard to disappear when the QLineEdit is out of focus. I am using matchbox for the virtual keyboard and am running:
keyboard->start("/bin/sh",QStringList()<<"keyboard.sh");
where the keyboard.sh file runs the matchbox-keyboard command to get the keyboard on screen.
The keyboard does pop up on screen when QLineEdit is in focus. I am unable to make it go away when it's out of focus.
Haven't tested that, but my idea would be to derive from QLineEdit and emit signals like focusGotten and focusLost (names from the top of my head, feel free to use any you prefer) accordingly (say, from focus[In|Out]Event), so they can call kill or terminate on the subprocess (when connected to those slots).
There's no "focusLost" signal but if you want to know when your widget has lost focus, override and reimplement void QWidget::focusOutEvent(QFocusEvent* event) in your widget.
It will be called whenever your widget has lost focus, at that point you can check if your keyboard is still visible (or if the process is still running) and do wathever you want.
EDIT
Here is an example on how to reimplement focus events:
In your .h file
class YourQLineEditClass : public QLineEdit
{
Q_OBJECT
.
.
.
protected:
void focusInEvent(QFocusEvent* e);
void focusOutEvent(QFocusEvent* e);
QProcess* keyboardProcess;
};
In your .cpp file
void YourQLineEditClass::focusInEvent(QFocusEvent* e)
{
// Create the keyboard process when line has focus
keyboardProcess = new QProcess(this);
keyboardProcess->start("/bin/sh", QStringList() << "keyboard.sh");
}
void YourQLineEditClass::focusOutEvent(QFocusEvent* e)
{
// Kill the keyboard process when line has lost focus
if (keyboardProcess != nullptr && keyboardProcess->isRunning())
{
keyboardProcess->terminate(); // or kill()
keyboardProcess->deleteLater();
}
}
So I have a QMainWindow and in its constructor I do the following stuff:
QStringList stringList;
stringList << "aaa" << "bbb" << "ccc";
QStringListModel *list = new QStringListModel(stringList);
ui->listView->setModel(list);
stringList.append("ddd");
list->setStringList(stringList);
QObject::connect(ui->listView->selectionModel(), &QItemSelectionModel::currentChanged, [&]() {
//do stuff
});
Why is the currentchanged emitted when the application starts and how can I avoid emitting the currentChanged until I actually click on the ListView?
[What's wrong?]
Since the listView is the only widget in your QMainWindow, it will be automatically focused as the application starts. Once the listView gets focused, the first item automatically becomes the current item if there wasn't already a current item. Hence the signal emitted.
[Solution]
Option 1
Add other widgets into your application and call QWidget::setFocus on one of them to make it the default focused widget as app starts.
Option 2
Call QListView::setFocusPolicy and make it Qt::ClickFocus, so the listView will only be focused if one of the items is clicked.
Option 3
The signal QItemSelectionModel::currentChanged has actually two arguments: QModelIndex ¤t and QModelIndex &privious. Use them by conventional signal/slot connection. For example
connect(ui->listView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(yourSlot(QModelIndex, QModelIndex)));
In the slots :
void MainWindow::yourSlot(QModelIndex cur, QModelIndex pre)
{
if(pre.isValid()) {
// do stuff
}
}
P.S. pre being invalid signifies that there was no current item previously. This bypasses the signal emit by auto-selected for the first time the listView is focused.
I have a Qt Desktop aplication which has several top-level widgets. Subwidgets of top-level widgets can be moved between top-level widgets by using drag-and-drop mechanism.
The problem i have now is to drop a sub-widget outside any of existing top-level widgets and create a new top-level widget to contain this one. Lets call this separation.
Can this be done using drag-and-drop? I could not find a way where my dropEvent goes?
Can i want to handle the drop event in my application even if the drop place is not allowed? Maybe a mouse release or something?
I cannot change everything now but also a question for the future. Is docking/undocking a better way to do this?
Regards
Mihai
I found a way to do this. When drag moves outside of the application widgets QDrag object emits a targetChanged signal with 0 parameter.
So i inherited from QDrag and then emit a custom signal in destructor if the target() is null.
The only problem is that the cursor looks like interdiction of drop and this i could not fix because QDrag can only set cursor pixmap for valid actions like Move or Copy or Link
Update:
Here is the inherited class.
class TabDrag: public QDrag
{
Q_OBJECT
public:
explicit TabDrag(QWidget *dragSource);
~TabDrag();
signals:
void tearOff(); /// emit tearOff signal if the QDrag object is destroyed and target was null
};
TabDrag::TabDrag(QWidget *dragSource):QDrag(dragSource)
{
}
TabDrag::~TabDrag()
{
// check if we need to detach this tab
if(!target())
{
emit tearOff();
}
}
The tearOff signal should be connected to whatever you want to happen. In my case i pull out the widget from the tab and change parent to a new window.
Example of usage
void MyTabBar::mouseMoveEvent(QMouseEvent* event)
{
..................
TabDrag * drag = new TabDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(*m_tabPixmap.data());
drag->setHotSpot(QPoint(m_dragStartPos.x() - tabAtRect.x(), m_dragStartPos.y() - tabAtRect.y()));
drag->exec();
connect(drag, SIGNAL(tearOff()), this, SLOT(onTearOff()));
}
I have a simple QT application with 10 radio buttons with names radio_1 through radio_10. It is a ui called Selector, and is part of a class called TimeSelector
In my header file for this design, i have this:
//! [1]
class TimeSelector : public QWidget
{
Q_OBJECT
public:
TimeSelector(QWidget *parent = 0);
private slots:
//void on_inputSpinBox1_valueChanged(int value);
//void on_inputSpinBox2_valueChanged(int value);
private:
Ui::Selector ui;
};
//! [1]
the commented out void_on_inputSpinBox1_valueChanged(int value) is from the tutorial for the simple calculator. I know i can do:
void on_radio_1_valueChanged(int value);
but I would need 10 functions. I want to be able to make one function that works for everything, and lets me pass in maybe a name of the radio button that called it, or a reference to the radio button so i can work with it and determine who it was.
I am very new to QT but this seems like it should be very basic and doable, thanks.
You can create a unique slot and obtain the object that emitted the signal with the QObject::sender() method. The following code presents an example of such slot:
public slots:
void onRadioToggled(bool checked)
{
QRadioButton *radio = qobject_cast< QRadioButton* >(QObject::sender());
// radio is the object that emitted the triggered signal
// if the slot hasn't been triggered by a QRadioButton, radio would be NULL
if (radio) {
qDebug() << radio->objectName() << " is set to " << checked << ".";
}
}
Note that radio->objectName() will not give you a good result unless you define it explicitly somewhere.
Now, you can connect the toggled(bool checked) signal of every QRadioButton to the onRadioToggled slot. Note that QRadioButton does not have any valueChanged signal so your code cannot actually work.
connect(radio_1, SIGNAL(toggled(bool)), SLOT(onRadioToggled(bool)));
connect(radio_2, SIGNAL(toggled(bool)), SLOT(onRadioToggled(bool)));
...
connect(radio_10, SIGNAL(toggled(bool)), SLOT(onRadioToggled(bool)));
In the radiobutton case, add the buttons to a QButtonGroup.
Similar functionality offers QSignalMapper.
What you can do is to create your own radio button class that inherits from QRadioButton and create a signal. This signal can have all the parameters you want.
void CheckWithReference(YourRadioButtonClass* rb);
or
void CheckWithReference(QString RadioButtonName);
or anything you would like to have.
Then create a slot in your TimeSelector class with the same set of parameters you will connect to all signals.
In Qt, when a widget receives focus, how can get a notification about it, so I can execute some custom code? Is there a signal or an event for that?
You can add en event filter.
This is an example of an application written with QtCreator. This form has a QComboBox named combobox.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->comboBox->installEventFilter(this);
.
.
.
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FocusOut)
{
if (object == ui->comboBox)
{
qWarning(object->objectName().toLatin1().data());
}
}
return false;
}
There is a "focusChanged" signal sent when the focus changes, introduced in Qt 4.1.
It has two arguments, he widget losing focus and the one gaining focus:
void QApplication::focusChanged(QWidget * old, QWidget * now)
Qt Designer isn't designed for this level of WYSIWYG programming.
Do it in C++:
class LineEdit : public QLineEdit
{
virtual void focusInEvent( QFocusEvent* )
{}
};
The simplest way is to connect a slot to the QApplication::focusChanged signal.
I'd have to play with it, but just looking at the QT Documentation, there is a "focusInEvent". This is an event handler.
Here's how you find information about.... Open up "QT Assistant". Go to the Index. Put in a "QLineEdit". There is a really useful link called "List of all members, including inherited members" on all the Widget pages. This list is great, because it even has the inherited stuff.
I did a quick search for "Focus" and found all the stuff related to focus for this Widget.
You have hit on of the weird splits in QT, if you look at the documentation focusInEvent is not a slot it is a protected function, you can override it if you are implementing a subclass of your widget. If you you just want to catch the event coming into your widget you can use QObject::installEventFilter it let's you catch any kind of events.
For some odd reason the developers of Trolltech decided to propagate UI events via two avenues, signals/slots and QEvent
Just in case anybody looking for two QMainWindow focus change .
You can use
if(e->type() == QEvent::WindowActivate)
{
//qDebug() << "Focus IN " << obj << e ;
}
QWidget::setFocus() is slot, not signal. You can check if QLineEdit is in focus with focus property. QLineEdit emits signals when text is changed or edited, see documentation.