QFrame : create mousePressEvent - qt

actually i'm trying to get a mousePressEvent for a QFrame in QT 5 (VS2010 with Qt-Addin). Saw so many suggestons here and on other forums, but newer got it to work, or i didnt understood the princip. Also looked at the scribble example, with no luck
How can i get the mousePressEvent for a QFrame? Do i have to create a class that is inheriting from a QFrame and then initialize this frame on my own in the main()-function? isnt there a solution that i can bind it to the Qt-Designer?
tried multiple things, mostly saw something like this:
protected:
void TestQtFormsApplication::mousePressEvent(QMouseEvent *qevent)
{
if (qevent->button() == Qt::LeftButton)
{
this->close();
}
};
with this i ever got the error C2027: use of undefined type 'QMouseEvent'

Subclass QFrame and reimplement mousePressEvent(..) much like you have in your example. Remember to accept() the event to stop it propagating to the parent widget. Your error is because QMouseEvent is only forward declared in the QWidget header file, just include it yourself.
If you want to use your subclass in Qt Designer, just use a QFrame and the 'Promote' it to your subclass (docs).

Related

Qt5 dynamic translation issues for C++ defined properties

I am currently working on somebody else code and I need to fix a bug linked with dynamic translation.
When the language is changed, the Loader is reloaded, it works but it generates unwanted effects (including the bug mentioned above).
So I tried to look for a way to dynamically change the translation without reloading everything.
I added m_engine->retranslate() in my switchLanguage function and this works perfectly, but only for texts directly defined in QML files. The thing is there is also a lot of text defined with setContextProperty in the C++ main controller class, and for them, it doesn't work at all (which seems pretty normal since m_engine is a QQmlApplicationEngine).
I don't see how I can simply force these texts to retranslate too. I have them in pretty much every controller function and they are used by different QML files. I am afraid that there will be no other choice but to change completely the way translation is managed. I hope advanced programmers can help me with this.
Other information:
I work with 5.13.0 version of Qt.
I don't use Designer and cannot use ui.retranslateUi().
It's hard to tell how your main controller class looks like, so here is a short general answer.
You can install an eventFilter and listen for LanguageChange.
In constructor of "main controller class", add this:
auto *core = QCoreApplication::instance();
if(core != nullptr)
{
core->installEventFilter(this);
}
Then add a function to your class:
bool MainControllerClass::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched);
if(event->type() == QEvent::LanguageChange)
{
//set properties again or emit property changed signals
}
}

Qt shortcut for custom context menu

I have been reading though a couple of examples and post but I just cannot figure out how to add a shortcut to my custom context menu. My GUI has several elements. One of them is a treeView. For the elements in my treeView I would like to have a custom context menu.
My first approach was according to this tutorial here. The context menu itself worked but the shortcuts cannot work if you create the actin within the show function.
So my second approach was according to this tutorial. But still my shortcuts do not work and if I use the context menu all actions are called twice...
Since I did not find a tutorial or code example, which matches my case, I hope that someone here can explain to me how this is correctly done in theory. Adding a shortcut to an action for a custom context menu.
Where do I have to declare my action?
What needs to be the parent of the action?
On which widget do I need to call addAction?
Thanks for any hints.
Another way is to add your action also to the parent widget (or main window widget). As mentioned in this reply, adding the same action to multiple widgets is fine and it's the way QActions are supposed to be used.
Example with custom HtmlBrowser class deriving from QTextBrowser:
Ctrl+U shortcut works for this code:
HtmlBrowser::HtmlBrowser(QWidget * parent) : QTextBrowser(parent)
{
viewSourceAct = new QAction(tr("View/hide HTML so&urce"), this);
viewSourceAct->setShortcut(tr("Ctrl+U"));
viewSourceAct->setCheckable(true);
parent->addAction(viewSourceAct);
connect(viewSourceAct, &QAction::triggered, this, &HtmlBrowser::viewSourceToggle);
}
and Ctrl+U shortcut does not work with this code (same as above, but without parent->AddAction(...)):
HtmlBrowser::HtmlBrowser(QWidget * parent) : QTextBrowser(parent)
{
viewSourceAct = new QAction(tr("View/hide HTML so&urce"), this);
viewSourceAct->setShortcut(tr("Ctrl+U"));
viewSourceAct->setCheckable(true);
connect(viewSourceAct, &QAction::triggered, this, &HtmlBrowser::viewSourceToggle);
}
Curiously, parent in this case is another widget (tab widget), not MainWindow. Still, adding parent->addAction() helps. And, unlike your suggested answer, it works even when connecting action to simple methods, without slots. Works for me in Qt 5.15.0. Not quite sure why it works, though. Perhaps, the widget the action is added to must be permanent for shortcuts to work? Looks like a bug in Qt.
Thanks to Scheff's hint I got it working. I do not now if this is really the correct way but this works for me.
The action needs to be declared in the constructor of your GUI class (e.g. MainWindow):
actionDel = new QAction(tr("delete"), this);
actionDel->setShortcut(QKeySequence(Qt::Key_Delete));
connect(actionDel, SIGNAL(triggered()), this, SLOT(actionDel_triggered()));
The triggered signal needs to be connected to a slot. Hint: if you create the slot do not use on_ACTIONNAME_triggered, this will interfere with the designer and cause a connection error.
Next add the action to a custom menu
fileContextMenu = new QMenu(this);
fileContextMenu->addAction(actionDel);
And to the widget
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDirContextMenu(QPoint)));
ui->treeView->addAction(actionDel);
All in the constructor of your GUI class.
To show the context menu use the following code in slot used in the above connect:
QModelIndex index=ui->treeView->indexAt(pos);
// Here you can modify the menu e.g. disabling certain actions
QAction* selectedItem = fileContextMenu->exec(ui->treeView->viewport()->mapToGlobal(pos));
If you do not have a slot for an action, the action can be also handled in the context menu slot, but this does not work with shortcuts!
if(selectedItem == actionOpen){
on_treeView_doubleClicked(index);
}

Proper way to encapsulate QWidgets?

I'm making a Qt widget (let us call it A) that really is a subclassed QGraphicsView. However, I don't want to expose QGraphicsView methods in my widget, just the basic QWidget interface and some of my own methods. Thus, I'd like to encapsulate an instance of A as a member of a simple QWidget subclass we'll call B.
Now I wonder, what is the proper way to draw this? So far I've given B a layout whose only item is the A member. But this feels sort of wrong; for example, I'll need to override default layout settings to avoid adding extra margins etc. This leads me to feel that there is some correct way to do this that I'm missing. Any thoughts?
Edit: In the setting of RedX' answer, my question becomes: What is the proper way to use gv in this setting? Give A a layout and add gv to it, or override A's painting methods to instead use those of gv? Or something else?
I don't think there is a better way. If you don't want to use a layout, you can override the parent's resizeEvent() like this:
void A::resizeEvent( QResizeEvent* ) {
m_graphicsView->setGeometry( QRect( 0, 0, size() ) );
}
I think you are trying to do this?
class A : public QWidget{
QGraphicsView* gv; //use this to do whatever you need
};
This should expose a as a QWidget and internally you'd use the gv to do whatever you need from the QGraphicsWidget.

Accessing the child UI elements in a Qt UI

I have defined a UI (let's call it myUI) using the Qt designer, and using it in my applications. I need to access all the sub-widgets (QToolButtons) in myUI. I want to get all the subwidgets as a QObjectList.
Is there any way to do this?
The QObject::children() doesn't work here because the Qt UI Compiler, when converting the .ui file to a C++ class, doesn't define the ui_myUI class as a subclass of any QObject derived class. Is there any way to force it to do this, and then use the children() function?
Thanks.
Call children() on the top level widget instance.
Assuming your top level widget is called 'tlWidget':
myUI->tlWidget->children()
Usually what happens is that you either inherit from the UI class or you have it as a member and invoke it's setupUi method, sending this as the parameter. The default in Qt Creator/Designer is to have it as a member, named ui.
You can use this member to access any widgets defined in your form.
You might find this interesting:
Designer: Using a .ui file in your application
How do you use your UI ?
(a) something like:
class MyWidget: public QWidget, protected myUI
{
//...
};
(b) or rather something like:
class MyWidget: public QWidget
{
protected:
myUI ui;
};
The Solution is similar for both cases, assumed that you call setupUi(this) or ui.setupUi(this) in the constructor of MyWidget
setupUi(QWidget* p) registers every widget of the UI as children of QWidget p,
so you can easily access them by calling the children() function of p:
this->children(); //"this" refers to an object of MyWidget

install EventFilter on QWidget (qt4.4.3/kde4)

I have a K* window, and within it, a widget which needs the events filtered.
For example I do not want the possibility of clicking it...
How can I do that?
Have I to use eventfilters? In this case, what's the best way?
but my problem is that I can't subclass my widget,because it's a TerminalInterface->widget(), not an object like others :\
Besides the setEnabled sledgehammer approach in the first answer, there are two other approaches, one of which is to use eventfilters.
The other is to subclass the widget, and then reimplement, say, the mouse* events. Simply leaving them empty will prevent any mouse interaction. So:
MyWidget : public QSomeWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent);
protected:
void mousePressEvent(QMouseEvent *) {}
.. etc ..
};
QWidget has an enabled property. Just call widget->setEnabled(false) and this will prevent it from accepting mouse clicks. It may also modify its appearance: for example a QPushButton will be grayed out.
Event Filters sound like overkill for what you want.
It looks like eventFilter() is what you want.
Here's the section of Qt docs that talk about it:
Event Filters
Basically you have to create a class that inherits QObject and then implement the virtual function eventFilter(). Then call the installEventFilter() method on the object that you want to filter with the filter as a parameter.

Resources