I have a QComboBox with several choices on a QToolBar. Every choice of the QComboBox will open a specific dialog window.
The problem I have is that after I choose the preferred index on the combobox no dialogs opens up. For simplicity of the example I am linking the same dialog to all choices:
dredgewindow.h
This is the header file
namespace Ui {
class DredgeWindow;
}
class DredgeWindow : public QMainWindow
{
Q_OBJECT
public:
explicit DredgeWindow(QWidget *parent = nullptr);
~DredgeWindow();
private:
Ui::DredgeWindow *ui;
DredgeDB *mDredgeDB;
};
dredgewindow.cpp
DredgeWindow::DredgeWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::DredgeWindow)
{
ui->setupUi(this);
QComboBox* myComboBox = new QComboBox;
ui->toolBarControls->addWidget(myComboBox);
myComboBox->addItem("Please Select");
myComboBox->addItem("Bucket");
myComboBox->addItem("Scow");
myComboBox->addItem("Hopper Dredger");
switch(myComboBox->currentIndex()){
case 0:
// do nothing
break;
case 1:
// Go to Bucket
mDredgeDB = new DredgeDB();
mDredgeDB->show();
break;
case 2:
// Go to Scow...
mDredgeDB = new DredgeDB();
mDredgeDB->show();
break;
case 3:
// Go to Hopper Dredger
mDredgeDB = new DredgeDB();
mDredgeDB->show();
default:
break;
}
}
DredgeWindow::~DredgeWindow()
{
delete ui;
}
So far I have been trying to trigger the opening of the dialogs using the combobox but as soon as I release the mouse (and therefore I switch - case) I expect the dialog to open but nothing happens. This source was useful even though it was not in c++. But still I used it to understand the general approach.
This approach triggers the combobox and set it active but other than that there is no specific indication.
Thanks in advance for pointing to the right direction for solving this problem.
You have to connect QComboBox::activated() signal to some slot.
Signals & Slots in Qt5
New Signal Slot Syntax
qOverload<>
This signal is sent when the user chooses an item in the combobox. The
item's index is passed. Note that this signal is sent even when the
choice is not changed. If you need to know when the choice actually
changes, use signal currentIndexChanged().
Note: Signal activated is overloaded in this class. To connect to this
signal by using the function pointer syntax, Qt provides a convenient
helper for obtaining the function pointer - qOverload<>.
class DredgeWindow : public QMainWindow
{
Q_OBJECT
...
private slots:
void on_combo_index_activated(int index);
...
};
DredgeWindow::DredgeWindow(QWidget *parent)
: QMainWindow(parent)
{
...
connect(myComboBox, QOverload<int>::of(&QComboBox::activated),
[=](int index) { on_combo_index_activated(index); });
...
}
void DredgeWindow::on_combo_index_activated(int index)
{
switch (index)
{
case 0:
// do nothing
break;
case 1:
// Go to Bucket
mDredgeDB = new DredgeDB();
mDredgeDB->show();
break;
case 2:
// Go to Scow...
mDredgeDB = new DredgeDB();
mDredgeDB->show();
break;
case 3:
// Go to Hopper Dredger
mDredgeDB = new DredgeDB();
mDredgeDB->show();
default:
break;
}
}
Related
I'm learning to use Qt and I want to extend the Terminal Example of Qt. I want to use its console.cpp in a QWidget from de Containers tab in the Design editor.
In the Terminal Example of Qt, this class is used like this:
ui->setupUi(this);
console = new Console;
console->setEnabled(false);
setCentralWidget(console);
But as I want to use it in a smaller QWidget I don't know how to set it, which method can I use as equivalent of setCentralWidget for my QWidget? Image of the Design tab with the widget I want to set to the QWidget class
Can I also use the same QWidget in several tabs?
The console.cpp code is the following one.
#include "console.h"
#include <QScrollBar>
#include <QtCore/QDebug>
Console::Console(QWidget *parent)
: QPlainTextEdit(parent)
, localEchoEnabled(false)
{
document()->setMaximumBlockCount(100);
QPalette p = palette();
p.setColor(QPalette::Base, Qt::black);
p.setColor(QPalette::Text, Qt::green);
setPalette(p);
}
void Console::putData(const QByteArray &data)
{
insertPlainText(QString(data));
QScrollBar *bar = verticalScrollBar();
bar->setValue(bar->maximum());
}
void Console::setLocalEchoEnabled(bool set)
{
localEchoEnabled = set;
}
void Console::keyPressEvent(QKeyEvent *e)
{
switch (e->key()) {
case Qt::Key_Backspace:
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Up:
case Qt::Key_Down:
break;
default:
if (localEchoEnabled)
QPlainTextEdit::keyPressEvent(e);
emit getData(e->text().toLocal8Bit());
}
}
void Console::mousePressEvent(QMouseEvent *e)
{
Q_UNUSED(e)
setFocus();
}
void Console::mouseDoubleClickEvent(QMouseEvent *e)
{
Q_UNUSED(e)
}
void Console::contextMenuEvent(QContextMenuEvent *e)
{
Q_UNUSED(e)
}
The Qt Example is this one: http://doc.qt.io/qt-5/qtserialport-terminal-example.html
Thanks so much!
If you're wanting to add it via designer just promote the QWidget that you added in your screegrab. (Right click > "Promote to..." > Fill in name & path to the console header).
Or not using promotion, you can add the console to a layout in code :
Console* console = new Console();
ui->your_layout_name_here->addWidget( console );
The problem is the following: I want to redefine (get rid of hovering effect of the button) the default Qt button style's behaviour. I only need 1 and 3 as shown on the picture under. The 2nd look comes when the button is focused.
Hovering effect: appears when you hover the button; remains painted when you press the button and move the cursor outside the space of the button.
What I've tried:
Redefining the events:
How do I implement QHoverEvent in Qt?
Here I simply redefined some of the events like Move, Hover etc. and made them non-functional.
Example Code:
class TestButton : public QToolButton
{
Q_OBJECT
public:
TestButton (QWidget *parent = 0) :
QToolButton(parent)
{}
bool event(QEvent * e)
{
this->clearFocus();
this->clearMask();
switch (e->type())
{
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverLeave:
case QEvent::GraphicsSceneHoverMove:
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
return true;
default:
return QWidget::event(e);
}
}
};
Some minor hacks:
btn->setFocusPolicy(Qt::NoFocus);
If you accept only HoverEnter events then after releasing the button the hover effect will go off as soon as you move mouse away. So you need to pretend moving mouse away by sending a corresponding event.
bool event(QEvent * e)
{
switch (e->type()) {
case QEvent::HoverEnter:
return true;
case QEvent::MouseButtonRelease: {
QEvent event(QEvent::Leave);
QApplication::sendEvent(this, &event);
}
default:
return QWidget::event(e);
}
}
I want to switch from one QToolButton to another in QToolBar. I have used QStackedWidget, their it is too simple to move from one widget to other but here I am not able to get how to move via using keyReleaseEvent.
mywindow::mywindow() : QMainWindow()
{
widget = new QWidget();
setCentralWidget(widget);
tool = new QToolBar();
vertical = new QVBoxLayout();
button1 = new QToolButton();
connect( button1, SIGNAL(clicked()), this, SLOT(fileNew()) );
button2 = new QToolButton();
button3 = new QToolButton();
button1->setIcon(QIcon("download.jpg"));
button1->setGeometry(0,0,100,200);
button2->setIcon(QIcon("images.jpg"));
button3->setIcon(QIcon("settings-icon.jpg"));
//stack1->addWidget(button1);
//stack1->addWidget(button2);
//stack1->addWidget(button3);
tool->addWidget(button1);
tool->addWidget(button2);
tool->addWidget(button3);
//tool->addWidget(stack1);
vertical->addWidget(tool);
widget->setLayout(vertical);
}
void mywindow::keyReleaseEvent(KeyEvent *event)
{
switch(event->key())
{
case:Qt::Key_Left:
}
}
You need to check against the focus, and shift that as appropriate. I would write something like this:
void mywindow::keyReleaseEvent(KeyEvent *event)
{
switch(event->key())
{
case:Qt::Key_Left:
if (button3->hasFocus())
button2->setFocus();
else if (button2->hasFocus())
button1->setFocus();
break;
case:Qt::Key_Right:
if (button1->hasFocus())
button2->setFocus();
else if (button2->hasFocus())
button3->setFocus();
break;
}
}
Note that this code can go tedious easily if you keep adding further buttons. I would place them into a container. Then, I would iterate through that container forward and reverse order depending on the focus switching logic.
See the documentation for further details:
focus : const bool
This property holds whether this widget (or its focus proxy) has the keyboard input focus.
By default, this property is false.
Note: Obtaining the value of this property for a widget is effectively equivalent to checking whether QApplication::focusWidget() refers to the widget.
Access functions:
bool hasFocus() const
I want to show or hide items in QStackedWidget. When I press Enter button it should show a stacked element and when I press say a left button it should hide.
I use QStackedWidget and QListWidget. My code:
mymainwindow.h:
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
class mymainwindow : public QMainWindow
{
Q_OBJECT
public:
mymainwindow();
protected:
void keyPressEvent(QKeyEvent *event);
private:
QStackedWidget *stack;
QListWidget *list;
QVBoxLayout *vertical;
QWidget *widget;
};
#endif
mymainwindow.cpp:
#include "mymainwindow.h"
mymainwindow::mymainwindow() : QMainWindow()
{
stack = new QStackedWidget();
list = new QListWidget();
stack->addWidget(new QLineEdit("Hello U have clicked the first menu"));
stack->addWidget(new QLineEdit("Second ListWidget Item"));
stack->addWidget(new QLineEdit("Last Widget Item"));
widget = new QWidget();
QLabel *label = new QLabel("Main Window");
list->addItem("New Item 1");
list->addItem("New Item 2");
list->addItem("New Item 3");
list->setFixedSize(200,100);
QVBoxLayout *vertical = new QVBoxLayout();
vertical->addWidget(label);
vertical->addWidget(list);
vertical->addWidget(stack);
widget->setLayout(vertical);
setCentralWidget(widget);
}
void mymainwindow::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Down:
connect(list, SIGNAL(currentRowChanged(int)), stack, SLOT(setCurrentIndex(int)));
break;
case Qt::Key_Up:
connect(list, SIGNAL(currentRowChanged(int)), stack, SLOT(setCurrentIndex(int)));
break;
case Qt::Key_Left:
break;
}
}
You will need to handle the Key_Left and Key_Enter cases in your key press event handler. It seems that you would simply like to show and hide the stackwidget based on the press of those two buttons. This is a simple QWidget operation, and the problem is not much related to QStackedWidget.
You would need to change the key press event code as follows:
void mymainwindow::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Down:
connect(list,SIGNAL(currentRowChanged(int)),stack,SLOT(setCurrentIndex(int)));
break;
case Qt::Key_Up:
connect(list,SIGNAL(currentRowChanged(int)),stack,SLOT(setCurrentIndex(int)));
break;
case Qt::Key_Left:
stack->show(); // <---- Added
break;
case Qt::Key_Enter: // <---- Added
stack->hide(); // <---- Added
break; // <---- Added
}
}
I'm trying get all the button child widgets of a window. The buttons were created through QDialogButtonBox. How do I get the which one is the cancel/ok/save button?
I have:
QWidget *pWin = QApplication::activeWindow();
QList<QPushButton *> allPButtons = pWin->findChildren<QPushButton *>();
QListIterator<QPushButton*> i(allPButtons);
while( i.hasNext() )
{
//identify which button is cancel/ok/save button here
/*Note: This is where I'm having trouble, getting the text of the
button here returns NULL. Any other way of Identifying which is
which?
Is it a special case when buttons are created through QDialogButtonBox?
*/
}
You should use the QDialogButtonBox::button() method, to get the button of the corresponding role.
For instance :
QPushButton* pOkButton = pButtonBox->button(QDialogButtonBox::Ok);
QPushButton* pCancelButton = pButtonBox->button(QDialogButtonBox::Cancel);
// and so on...
Generally speaking, I would say it's a bad idea to find a button from it's text, as this text might change when you app is internationalized.
One way is by text parameter from constructor such as QPushButton(const QString & text, QWidget * parent = 0):
QPushButton* buttonSave = new QPushButton("Save");
// etc..
while( i.hasNext() )
{
//identify which button is cancel/ok/save button here
if(i.next()->text() == "Save") {
// do something to save push button
}
}
Another alternative solution:
Use QDialogButtonBox's buttons function to return a list of all the buttons that have been added to the button box, then iterate over the list and identify each button using QDialogButtonBox's standardButton.
auto buttons = ui->buttonBox->buttons();
for (auto button : buttons) {
switch (ui->buttonBox->standardButton(button)) {
case QDialogButtonBox::Ok:
// do something
break;
case QDialogButtonBox::Cancel:
// do something
break;
case QDialogButtonBox::Save:
// do something
break;
default:
break;
}
}
For non-standard buttons
Map each button to an enum:
.h file:
private:
enum class NonStandardButton { Undo, Redo };
// map of non-standard buttons to enum class NonStandardButton
QHash<QAbstractButton*, NonStandardButton> buttonsMap;
.cpp file:
// in constructor
auto undoQPushButton =
ui->buttonBox->addButton("Undo", QDialogButtonBox::ActionRole);
auto redoQPushButton =
ui->buttonBox->addButton("Redo", QDialogButtonBox::ActionRole);
buttonsMap.insert(undoQPushButton, NonStandardButton::Undo);
buttonsMap.insert(redoQPushButton, NonStandardButton::Redo);
Then use QDialogButtonBox::NoButton to identify non-standard buttons:
switch (ui->buttonBox->standardButton(button)) {
case QDialogButtonBox::NoButton:
switch (buttonsMap.value(button)) {
case NonStandardButton::Undo:
// do something
break;
case NonStandardButton::Redo:
// do something
break;
default:
break;
}
default:
break;
}