Why are treeview items only "activated" with double-click on Windows?
-
The standard behaviour on Windows in treeviews is that a single click activates them (selects them). Also, right clicking also activates them (and brings up a potential context menu).
Qt behaviour is fundamental different from what users expect it to be. Why and how can I circumvent this? -
You must be doing something strange because the default behavior is what you described - single click selects an item, double click expands/collapses a tree.
Maybe if you could give us some details of what you are doing or show some code? -
I created sample project:
test.ui
@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TreeViewActivationClass</class>
<widget class="QMainWindow" name="TreeViewActivationClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>TreeViewActivation</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QTreeWidget" name="tree">
<property name="geometry">
<rect>
<x>0</x>
<y>10</y>
<width>256</width>
<height>192</height>
</rect>
</property>
<column>
<property name="text">
<string>1</string>
</property>
</column>
<item>
<property name="text">
<string>Item1</string>
</property>
</item>
<item>
<property name="text">
<string>Item2</string>
</property>
</item>
<item>
<property name="text">
<string>Item3</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>230</y>
<width>53</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="treeviewactivation.qrc"/>
</resources>
<connections/>
</ui>
@test.h
@
#include <QtWidgets/QMainWindow>
#include "ui_treeviewactivation.h"class TreeViewActivation : public QMainWindow
{
Q_OBJECTpublic:
TreeViewActivation(QWidget *parent = 0);
~TreeViewActivation();private Q_SLOTS:
void onItemActivated(const QModelIndex& index);
private:
Ui::TreeViewActivationClass ui;
};
@test.cpp
@
#include "test.h"TreeViewActivation::TreeViewActivation(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.tree, &QTreeView::activated, this, &TreeViewActivation::onItemActivated);
}void TreeViewActivation::onItemActivated(const QModelIndex& index) {
ui.label->setText(index.model()->data(index, Qt::DisplayRole).toString());
}
@The label changes its text only on double click on tree items
-
Hi,
Can you also give which version of Qt and windows you are using ?
-
Ah, I didn't get what you meant the first time.
The problem you have here is that selecting is not the same as activating an item. At least on Windows. I don't know much about other platforms.Think about it in terms of windows explorer - single clicking an item selects it, makes it current for keyboard navigation etc., but it doesn't activate it (by default, there are options to change it). You double click or hit return/enter to activate an item (run a program or open a folder).
I don't know why you think this is not standard but that's how it is on Windows.You can look into other signals, like clicked or one of the selection model ones: selectionChanged or currentChanged. Maybe one of these is what you need.
-
@SGalst: Win 8, Qt 5.2-beta1
@Chris: Single click is the standard in Explorers left tree pane (not in the Item view on the right). Other signals are not the same:
clicked should work, but doesnt, since a right click also "selects" an item without a chance to prevent that. And there is no signal to catch for right clicks, is there?
selectionChanged/currentChange have weird side effects. When the treeview is first displayed and does not have the focus and I have other content in the same (Main)Window that I disable on button click (like when u press "Login" button I disable the email&password fields). What then happens is that Qt searches for the next focus control which sometimes (after the firststart of the application) happens to be the treeview and it emit a selectionChange event without (!) actually changing the selection (visually).
So its all, yet again, non-platform conform things I have to fight with Qt. Its a nice framework, but there are such quirks sometimes that cost so much time. A plain win32 listview is pretty painless on the other hand. -
Yeah, I was thinking about the main panel of the explorer window. I'm not too sure if that is the "standard" way a tree should behave but I'll admit my winapi is a bit rusty ( who uses it these days anyway, it's so clunky :P )
Well I guess a sorta motto of Qt always was to make the most common things easy and other things possible, and it's one of these cases.
But enough of that, we could probably discuss this all day long :)The clicked signal is emitted only for left button, as this is considered the trigger button. To get all buttons connect to the pressed signal. If you need to know which button was pressed exactly you can check QApplication::mouseButtons() state inside the slot.
-
See that's the problem. I don't want to know which button the user clicked, I want the activated signal only be signalled if he uses the left button (as it does) but when he clicks an item with the right button (which is the context menu click on Windows) either nothing should happen if no context menu is attached (which I don't have) or the activated signal should be emitted. Why do I have to go in now and do all those checks myself? Because at the moment, you can select an item with right click, but its not activated. That clearly is a bug from the users standpoint.
-
It's definitely not a Qt bug. It's just not how you want it in your particular case and it's your job in that case to make it work like you want it to.
Imagine a "Select folder" dialog with a directory tree view. It would be extremely annoying if a single click opened a directory in that case. Imagine a file tree in an IDE. It would be bad if a single click (even worse with right click) opened a file right away.
There are simply two ways this can work and what Qt implements as a default is not what you need in your particular case. Don't rush into calling it a bug. What you want is still possible and not that hard really. Just connect to pressed and check your buttons. If it's left button do your thing. If it's right button and there's no context menu do your thing. It's like 3 lines of code.
-
As I wrote, I couldn't care less for what button was pressed. So the "pressed" signal is the one I am going with, it seems to do what I want. Thanks