currentChanged fires immediately upon initialization?
-
I have a class that is derived from QTreeView and I want to get notified that a selection has occurred in the view. The problem is that currentChanged is fired immediately upon the startup of my app where my views are being initialized, as if a row was already selected, which it hasn't.
How does one go about not having currentChanged fire till a user selects a row, and not upon initialization?
-
Hi,
Can you show how you are setting up your widgets ?
-
class CarsWidget : public QWidget { ... }; class CarsTreeView : public QTreeView { ... }; CarsWidget::CarsWidget(MainWindow *win, QWidget *parent) : main_win(win), QWidget(parent) { view = new CarsTreeView(win); view->setModel(model); QVBoxLayout *carsLayout = new QVBoxLayout; carsLayout->addWidget(view); carsLayout->setContentsMargins(0, 0, 0, 5); setLayout(carsLayout); } CarsTreeView::CarsTreeView(MainWindow *win, QWidget *parent) : mainWin(win), QTreeView(parent) { } void CarsTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { cout << "currentChanged()\n"; win->changeSelectedTab("Wheels"); }
The currentChanged() function is fired as soon as all this is created. My intention is that, when the user clicks on a row, a new tab will appear, but the tab appears too soon as this is fired upon creation.
-
You should check the validate of the index passed and react properly on that.
From the portion of code you are showing, there's an architectural problem that is going to make your application hard to maintain. Why does the CarsTreeView class need to know the QMainWindow ? You are creating an unnecessary tight coupling here.
If you want something to happen when currentChanged is called, you should rather emit a message from that function and connect your main window to it. It's not the responsibility of a widget to modify a parent.
-
Ah, ok, that makes sense.
And this brings up a good point that I'm not quite clear on.
The reason I pass the MainWindow into CarsTreeView is because, if I understand correctly, to emit a signal to a slot means you must have the object to emit the signal to. E.g., ...
connect(got_selection, &CarsTreeView::send_my_selection, mainWin, &MainWindow::show_tab);
But I can't see the difference in doing
emit show_tab(idx);
versus ...
mainWin->show_tab(idx);
-
show_tab is a slot, you don't emit a slot, you emit a signal.
-
@SRaD said in currentChanged fires immediately upon initialization?:
if I understand correctly, to emit a signal to a slot means you must have the object to emit the signal to
This is wrong. You only need the object to connect a signal to a slot. Emitting signal does not require to know who is connected to the signal. That is one of the advantages of signals/slots. The connect() method should be called inside main window - here you have both objects to connect.
"But I can't see the difference in doing" - connect does not call anything (it does NOT emit signal). All it does is connecting a signal to a slot. If you later do "emit someSignal()" then all slots connected to that signal will be called.
-
@SRaD you may want to think of connect, signal and slot as wiring, switch and bulb respectively.
With connect() you wire the switch to the bulb, then when you emit a signal is like actuating the switch so the electricity ends up in the bulb (the slot) where you carry on things (light your room).