Toggle A QAction To Set QStackedWidget's Current Widget - qt

So what I am trying to do is when I press the showMenu (QAction), the container (QStackedWidget) changes the current widget to menuWidget AND when I press it again it hides.
Ok so I have managed to get this code:
connect(showMenu, SIGNAL(triggered()), map, SLOT(map()));
map->setMapping(menuWidget, container);
Object::connect(map, SIGNAL(mapped(QWidget *)), container, SLOT(setCurrentWidget(QWidget *)));
also if I run:
container->setCurrentWidget(menuWidget);
directly, it works fine, so I have not messed up in that way.

You should create a slot in your class where you show/hide menuWidget.
If you are using a checkable QAction object, then you can use QAction::toggled(bool checked) signal, and use the checked variable to determine if you should show or hide your widget.
If you're not using a checkable QAction object, then you should create a class member variable of type bool that you toggle in your slot:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
...
private:
bool toggleStatus; // set this to false in your constructor
...
};
 
void MainWindow::menuToggled()
{
toggleStatus = !toggleStatus;
if(toggleStatus)
{
container->setCurrentWidget(menuWidget);
}
else
{
container->setCurrentWidget(mdiContainer);
}
}

Related

Pressing Tab in QTextEdit in Dialog - change behavior

I have QDialog that contains few buttons and a QTextEdit.
after writing something in the QTextEdit, I press tab in order to get to one of the buttons, but when I pressing tab, a tab space is added to the QTextEdit. How can I change this behavior?
You can use setTabChangesFocus method of QTextEdit:
yourTextEdit.setTabChangesFocus(true);
You can subclass QTextEdit and override the keyPressEvent to intercept the tab key. Then, use nextInFocusChain to determine the next focus widget and call setFocus on it
Outline:
class MyTextEdit : public QTextEdit
{
public:
MyTextEdit(QWidget *parent = 0) : QTextEdit(parent) {}
protected:
void keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Tab) {
nextInFocusChain()->setFocus(Qt::TabFocusReason);
} else {
QTextEdit::keyPressEvent(e);
}
}
};

Identifying which label was clicked in qt

I have 10 Qlabels with an image on each. When i click on a label, its image should be cleared. I am able to identify which label was clicked theorotically, using the pixel clicked and size of each image. But how to use that information?
Eg. each label has dimension 100*100, the first label starting from 0,0. if pixel clicked is 250,50, i know that the third label was clicked, but how to use this to clear the label.
Im stuck.
There are a few ways how to implement it.
First. I would recommend to use a new class that inherits QLabel and overloads mouseReleaseEvent() handler where you just call clear() method. In this case the label will detect the mouse clicks itself and will clear its content internally.
class SelfClearingLabel : public QLabel
{
public:
using QLabel::QLabel;
protected:
void mouseReleaseEvent(QMouseEvent * event)
{
if (event->button()==Qt::LeftButton)
// process only clicks on the left button
{
clear();
}
QLabel::mouseReleaseEvent(event);
}
};
Second. You can catch mouseReleaseEvent() in your top widget and iterate over all of your child QLabel widgets and check which one is currently under mouse and clear the one. If you have other labels on this widget that shouldn't be cleared on mouse clicks then you can add some property to the QLabels that are under your interest.
void SomeTopFrame::createImageLabels(int count)
{
for (int i=0;i<count;i++)
{
QLabel* label=new QLabel(this);
label->setProperty("clear_on_click",true);
// assume that labels are added to layout *m_labelsLayout;
m_labelsLayout->addWidget(label);
}
}
void SomeTopFrame::mouseReleaseEvent(QMouseEvent * event)
{
if (event->button()==Qt::LeftButton)
// process only clicks on the left button
{
QList<QLabel*> labels=findChildren<QLabel*>();
foreach (QLabel* label, labels)
{
if (label->property("clear_on_click")&&label->underMouse())
{
label->clear();
break;
}
}
}
QFrame::mouseReleaseEvent(event);
}
It is a sample code just to show the principle. In production you can add a check that mouseReleaseEvent() is on the same widget as the mousePressEvent() to avoid triggering on drag and drop events.
Create the custom class that inherit QLabel :
ClickableLabel.h
class ClickableLabel : public QLabel
{
Q_OBJECT
public:
explicit ClickableLabel( const QString& text="", QWidget* parent=0 );
~ClickableLabel();
signals:
void clicked();
protected:
void mousePressEvent(QMouseEvent* event);
};
ClickableLabel.cpp
ClickableLabel::ClickableLabel(const QString& text, QWidget* parent)
: QLabel(parent)
{
setText(text);
}
ClickableLabel::~ClickableLabel()
{
}
void ClickableLabel::mousePressEvent(QMouseEvent* event)
{
emit clicked();
}
Just connect all labels clicked signal to following slot :
MyClass::labelClicked()
{
ClickableLabel *label = (ClickableLabel*)QObject::sender;
if(label)
label->clear();
}

QWidget can we get/modify existing context menu of a widget

I have third party widget which provides me some context menu. Lets say cut, copy paste, select all.
Now I just want to modify only the paste functionality of the existing context menu. I know that I can implement whole context menu from scratch in the contextMenuEvent. But I do not want to do that as I am satisfied with other context menu actions, and just want to modify only the paste functionality.
I am using QT 4.8 on Mac OSX.
If such a thing is not possible at the moment can someone give me link/reference for that ? So that I can satisfy my stakeholders.
Edit: To be more clearer on what I am trying to do is, disable the paste context menu for some reason, and want to enable it later on depending on the situation/events.
I'm not sure that it can be done in a common way.
Here is a tricky solution:
In contextMenuEvent create a queued call to some slot:
QMetaObject::invokeMethod(this, "patchMenu", Qt::QueuedConnection);
Get visible windows in the slot and find QMenu. Get actions out of it and enable/disable them:
Q_SLOT patchMenu()
{
QWidgetList widgets = QApplication::topLevelWidgets();
foreach (QWidget* widget, widgets)
{
if (QMenu* menu = qobject_cast<QMenu*>(widget))
{
QList<QAction*> actions = menu->actions();
// here you can either get an action by index actions[5]
// or search the action by text
actions;
}
}
}
EDIT:
Here is a working example which demonstrates this approach:
window.h
#pragma once
#include <QtGui>
class Window: public QMainWindow
{
Q_OBJECT
public:
Window(QWidget *parent = 0);
};
class A : public QWidget
{
public:
virtual void contextMenuEvent(QContextMenuEvent* e);
};
class B : public A
{
Q_OBJECT;
public:
virtual void contextMenuEvent(QContextMenuEvent*);
Q_SLOT void patchMenu();
};
window.cpp
#include "window.h"
Window::Window(QWidget *parent) : QMainWindow(parent)
{
setCentralWidget(new B());
}
void B::patchMenu()
{
QWidgetList widgets = QApplication::topLevelWidgets();
foreach (QWidget* widget, widgets)
{
if (QMenu* menu = qobject_cast<QMenu*>(widget))
{
QList<QAction*> actions = menu->actions();
// here you can either get an action by index actions[5]
// or search the action by text
actions;
}
}
}
void B::contextMenuEvent(QContextMenuEvent* e)
{
QMetaObject::invokeMethod(this, "patchMenu", Qt::QueuedConnection);
A::contextMenuEvent(e);
}
void A::contextMenuEvent(QContextMenuEvent* e)
{
QMenu menu;
QAction* action = new QAction(QIcon(), "text", &menu);
menu.addAction(action);
menu.exec(e->globalPos());
}

keep Focus on QGLWidget with QCheckBox and QPushButton in MainWindow

I have a Qt main window with QCheckBox and QPushButton and a sub QGLwidget class widget for graphics rendering.
I have put into void Ui_MainWindow::setupUi(QMainWindow *MainWindow) member function :
void Ui_MainWindow::setupUi(QMainWindow *MainWindow)
{
pushButton_2 = new QPushButton(widget);
...
checkBox_3 = new QCheckBox(widget);
...
widget_2 = new GLWidget(widget);
widget_2->setFocusPolicy(Qt::StrongFocus);
widget_2->setFocus();
...
}
I have created signals which modify the graphics rendering of widget_2 :
void Ui_MainWindow::createSignals()
{
...
connect(pushButton_2, SIGNAL(clicked()), this, SLOT(pauseSimu()));
connect(checkBox_3, SIGNAL(clicked()), this, SLOT(hideClassic()));
...
}
To always keep the focus on widget_2 despite clicking on pushButton_2 or checkBox_3, I have to put into pauseSimu() and hideClassic() :
void Ui_MainWindow::pauseSimu()
{
widget_2->setFocus();
...
}
and
void Ui_MainWindow::hideClassic()
{
widget_2->setFocus();
...
}
The key events on widget_2 GLWidget are coded in the GLWidget class member functions.
How could I avoid to use setFocus() in all signals functions for always keeping the focus on widget_2 GLWidget ?
Try calling setFocusPolicy(Qt::NoFocus) on your button and checkbox.

Custom context menu connecting in Qt

I have a problem with connecting custom menu in QListWidget, the connect function returns false. Here is the code:
I've got some main window class called MainWindow. In its constructor I have this line
connect(ui->notesWidget, SIGNAL(customContextMenuRequested(QPoint &)),
this, SLOT(contextMenuforNotesArea(QPoint &)));
where notesWidget is mentioned QListWidget.
ContextMenuforNotesArea(QPoint &) is defined like this
class MainWindow : public QMainWindow
{
public slots:
void contextMenuforNotesArea(QPoint &pos);
};
void MainWindow::contextMenuforNotesArea(const QPoint &pos){
QMessageBox::information(this, "a", "the function has been finally called");
QMenu contextMenu(tr("Context menu"), this);
contextMenu.addAction(new QAction(tr("Hello"), this));
contextMenu.exec(mapToGlobal(pos));
}
I have also changed the property contextMenu in the listWidget to customContextMenu through form designer.
Change your SLOT signature as follows in the header file
void contextMenuforNotesArea(const QPoint &pos);
Also make sure, when you are doing the connection in the constructor, you do it after the calling of setupUi

Resources