How can i click on a QGroupBox's CheckBox programatically - python

I want to click on the builtin (enabling) checkbox of a QGroupBox programmatically during testing with pytest-qt.
But i can't find out how to access the underlying checkbox widget of the groupbox via an attribute or similar methods.
Basically i could just use the .setChecked(True) method in my test but this would not be a "real" mouse click.
Is there a to access the checkbox widget of the groupbox directly?

Click action involves pressButton and releaseButton mouse events. So we can emulate click action by sending two sequential events to the destination widget.
Widget::Widget(QWidget* parent)
: QWidget(parent)
, m_groupBox(new QGroupBox)
{
m_groupBox->setCheckable(true);
QPushButton* generateClickButton = new QPushButton("generate click");
connect(generateClickButton, &QPushButton::clicked, [this]
{
clickAt(m_groupBox, Qt::LeftButton);
});
setLayout(new QVBoxLayout);
layout()->addWidget(m_groupBox);
layout()->addWidget(generateClickButton);
resize(100, 100);
}
Widget::~Widget()
{}
void Widget::clickAt(QWidget* receiver, Qt::MouseButton button)
{
if (receiver)
{
QMouseEvent pressEvent(QEvent::MouseButtonPress, receiver->pos(), button, 0, 0);
QMouseEvent releaseEvent(QEvent::MouseButtonRelease, receiver->pos(), button, 0, 0);
QApplication::sendEvent(receiver, &pressEvent);
QApplication::sendEvent(receiver, &releaseEvent);
}
}
Better alternative: QTest::mouseClick does the same

Related

How to implement list of checkable buttons with pyqt

I want to implement list of radiobuttons, but radiobutton shouldn't have a circle and if radiobutton is checked, then the background color is different from the others.
Like in this photo.
(https://i.stack.imgur.com/LsOeE.png)
I think I can use radiobuttons or tabs, but i don't know how to change the styles of this things. Tell me a widget with similar logic or how to change the style of radiobuttons/tabs.
If you don't need the circle of a radio button, then you probably don't need a radio button at all.
Instead, use standard QPushButtons (or QToolButtons) with setCheckable(True) and add them to a QButtonGroup.
win = QWidget()
win.setStyleSheet('''
QPushButton[checkable="true"]::checked {
background: red;
}
''')
layout = QHBoxLayout(win)
group = QButtonGroup()
for title in 'cdefgh':
button = QPushButton(title)
layout.addWidget(button)
button.setCheckable(True)
group.addButton(button)
group.buttons()[0].setChecked(True)
i set css rule:
css = '''
QRadioButton::indicator {
image: none;
}
QRadioButton::checked
{
background-color : red;
}
'''
radioButton.setStyleSheet(css)

how to sent Information from ComboBox to Python

I have a simple code nothing crazy but i just can't figure out how i can sent information from ComboBox to Python. I know the connection between pyton and qml is good, becouse i can sent other strings to python from qml.
Thanks in advance
Funcy.py
#pyqtSlot(str)
def mail(self, dropdown):
print(dropdown) #should print Yes or No
Gui.qml
ComboBox
{
id: dropdown
// those are the options a user could choose
model: ["No", "Yes"]
}
Button
{
// some styling
onClicked
{
backend.mail(dropdown.text)
}
}
If you want to send the selected text from the ComboBox when the Button is pressed then you must send the currentText:
onClicked: backend.mail(dropdown.currentText)

Change the icon of QPushbutton or QToolbutton

Icons for various states of QPushbutton etc.
How do set the icon for a QPushButton or QToolbutton for when it is off and for when it is toggled.
btn1 = QPushButton("Test")
icon1 = QIcon("normal.png")
icon2 = QIcon("toggled.png")
# set the icon for when btn1.toggled returns True
# and when btn1.toggled returns False
Creating a QPushbutton with three states
I want to create a qpushbutton that can have three states. I am using the button in a media player I am creating. These are the states I want the button to have:
normal (repeat off)
toggled state 1 (repeat all)
toggled state 2 (repeat one)
Upon research I've realised I may have to override QAbstractButton.nextCheckState. The trouble is that the is no signature for the method in the documentation. I therefore have no idea on how to override it or even if the is a state property to set or modify.
Any help will be appreciated.
You can use a simple way of checking the checked flag of a pushbutton on the clicked() signal.
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(buttonClicked(bool)));
And in your code, define a slot as buttonClicked(bool checked) and implement it as:
void MainWindow::buttonClicked(bool checked)
{
if ( checked )
ui->pushButton->setIcon(QIcon(":/on.png"));
else
ui->pushButton->setIcon(QIcon(":/off.png"));
}
This can be implemented for a QToolbutton as well accordingly.
And please note the icons in here are used from the resources. So, it's better to add your icons to the resources file.
I don't know about QAbstractButton.nextCheckState, but I suggest making use of Qt's signal/slot mechanism.
Whenever the state of repeat mode changes in the model, emit a signal like notifyModeChanged. Connect a slot to that signal in which the state (e.g. the icon) of the button is set as required.
I put together a quick example with everything contained in the MainWindow class. In a real application one would divide the code at least into model and view. The example is based on the auto-generated project of QtCreator's new project wizard. In Design view, I added a QPushButton.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ui_mainwindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) :
QMainWindow(parent),
ui(new Ui::MainWindow),
icon1("icon1.png"),
icon2("icon2.png"),
icon3("icon3.png")
{
ui->setupUi(this);
ui->pushButton->setIcon(icon2);
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::changeMode);
connect(this, &MainWindow::notifyModeChanged, this, &MainWindow::modeChanged);
}
~MainWindow() {
delete ui;
}
signals:
void notifyModeChanged();
public slots:
void changeMode() {
mode = (mode + 1) % 3;
emit notifyModeChanged();
}
void modeChanged() {
switch (mode) {
case 0: ui->pushButton->setIcon(icon1); break;
case 1: ui->pushButton->setIcon(icon2); break;
case 2: ui->pushButton->setIcon(icon3); break;
}
}
private:
Ui::MainWindow *ui;
QIcon icon1;
QIcon icon2;
QIcon icon3;
int mode{0};
};
#endif // MAINWINDOW_H

Can we call the button using select(A single selection widget) in bokeh?

https://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html (You can see select)
I want to call a button, text input and slider in using select.
plot_button = Button(label="plot")
color_button = Button(label="Color", disabled=True)
axis_start_value_text = TextInput(title=" Start value=", value="270")
axis_slider = Slider(value=0, start=0, end=100, step=1, title="Title")
button_map = {
"plot": plot_button,
"Color": color_button,
"Start value": axis_start_value_text,
"Slider": axis_slider
}
button_call = Select(title="Button call", options=sorted(button_map.keys()),
value="plot")
In the Select button, when I click on a button, text_input and slider the button appears on the screen that I clicked. İs it possible?
I put up an example app on bitbucket.
You can give css_classes to your widgets, or widgetbox, and then access the div elements contaning the widgets in a CustomJS callback.
I have not found a way to set the display to None from the start, couldn't do it with customm css. So I use a timeout function, you'd need to tweak the timing of the timeout function if you don't want the widgets to appear before they are made invisible.
EDIT:
I updated the code, in fact there is a clean way to hide the widgets initially without using a timeout callback. I use a custom css for that with display:none for all objects with class "hidden". Then in the CustomJS you just need to add or remove the "hidden" to the class name of the widgetboxes.

PyQt: Can a QPushButton be assigned a QAction?

Using Python 3.2x and PyQT 4.8x:
I initialized an action and assigned to a menu item:
self.__actionOpen = QtGui.QAction(self.__mw)
self.__actionOpen.setObjectName("actionOpen")
self.__actionOpen.setText("OpenFile")
QtCore.QObject.connect(self.__actionOpen, QtCore.SIGNAL("triggered()"), self.__accessFile)
self.__menuFile.addAction(self.__actionOpen)
Works fine - menu item is there with caption "OpenFile" and the action signal/slot is invoked.
I tried it with a QPushButton - same QAction object:
self.__buttonFile.addAction(self.__actionOpen)
Nothing: No caption on the button, nothing happens when it's clicked.
Do actions not work with QButton (the addAction call did not complain...)? Or is there something wrong with my code? Perhaps the "triggered()" signal is not appropriate for an action that interacts with QPushButton?
You can't assign a QAction to a QPushButton the way you want. QPushButton doesn't redefine addAction so the behavior comes from QWidget.addAction which adds the action to the context menu of the button.
You can however assign the action to a QToolButton with setDefaultAction which will change the button caption and trigger the action when clicked.
Or you could do it manually anyway by subclassing QPushButton and adding a setDefaultAction method that would change everything in the button according to the action (caption, tooltip...) and connects the relevant button's signals to the action's slots.
Adding an action won't "run" the action when the button is clicked, and that is by design.
If what you are after is to reuse or refer the QAction's behaviour you can just connect the clicked() signal of the QPushButton to the trigger() of the QAction:
QtCore.QObject.connect(self.__menuFile,
QtCore.SIGNAL("clicked()"),
self.__actionOpen.trigger)
That way the self.__actionOpen action will be triggered whenever the self.menuFile button is clicked.
My solution for this issue:
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QPushButton
class QActingPushButton(QPushButton):
"""QPushButtons don't interact with their QActions. This class triggers
every `QAction` in `self.actions()` when the `clicked` signal is emitted.
https://stackoverflow.com/a/16703358
"""
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.clicked.connect(self.trigger_actions)
#pyqtSlot()
def trigger_actions(self) -> None:
for act in self.actions():
act.trigger()
You could create a PushButtonAction:
h file:
#ifndef PUSHBUTTONACTION_H
#define PUSHBUTTONACTION_H
#include <QAction>
#include <QPushButton>
class PushButtonAction: public QPushButton
{
Q_OBJECT
public:
PushButtonAction(QAction *action, QWidget *parent = 0);
};
#endif // PUSHBUTTONACTION_H
cpp file:
#include "pushbuttonaction.h"
PushButtonAction::PushButtonAction(QAction *action, QWidget *parent):
QPushButton(parent)
{
setIcon(action->icon());
setText(action->text());
connect(this, SIGNAL(clicked()), action, SLOT(trigger()));
}

Categories

Resources