Adjust QCheckbox into QTableWidget : Qt - c++

I am facing issues when I adjust QCheckbox into QTableWidget.
It is working as expected in Mac and Linux but creating problem in Windows.
I have googled it and tried out different solutions, but it did not solve my problem.
Code:
QWidget* cellWidget = new QWidget();
QCheckBox *box = new QCheckBox();
box->setCheckState(Qt::Unchecked);
QHBoxLayout* layout = new QHBoxLayout(cellWidget);
layout->addWidget(box);
layout->setAlignment(Qt::AlignCenter);
layout->setContentsMargins(0, 0, 0, 0);
cellWidget->setLayout(layout);
ui->twidget_header->setCellWidget(0, 0, cellWidget);
Mac OS O/P : As Expected
Win OS O/P : Problem with Checkbox size and alignment
.
My app is created in Qt 5.9 for Mac, Win and Linux platform.
Let me know if you required more info about the problem.

The design and size of the widgets are determined by the style. To override the native style (whatever QApplication sets as default on your target system) you'll have to derive your own QStyle for that target system and and reimplement pixelMetric() to return the appropriate values for QStyle::PM_IndicatorWidth and QStyle::PM_IndicatorHeight (I think; didn't check that).

The problem can happen with any QWidget while you create Qt app and support different resolutions.
To overcome the size of the QWidget (QCheckbox/QRadiobutton), you just need to overwrite the QWidget class.
Create customcheckbox.h file and overwrite the QCheckbox widget.
class CustomCheckBox : public QCheckBox
{
Q_OBJECT
public:
CustomCheckBox(QWidget *parent=NULL);
private:
bool m_isChecked;
public slots:
void emitToggleSignal(bool);
};
Implement customcheckbox.cpp file as per your requirement.
By doing this, QCheckbox will automatically adjust size on respective resolution.
Hope this will save someone's time in future.
Thanks.

Related

Setting an icon's size on a QPushButton through Stylesheets

I'm trying to set an icon's size on a QPushButton through Stylesheets. I am unable to locate the proper syntax from the Qt documentation that would allow me to modify the icon's size when I implement the icon image from the stylesheet. This application is for use on the icon of a QPushButton on multiple uis and the Stylesheet settings will be set on a parent ui.
This is my code, based on this suggestion. Adjusting the size to 64 or 256 did not change the size of the object.
"QPushButton#pushButton_Calibration {image: url(:/images/toolkit.png); qproperty-iconSize: 128px;}"
This is my other code, based on this other suggestion. Adjusting the width/height to 64 or 256 did not change the size of the object.
"QPushButton#pushButton_Calibration {image: url(:/images/toolkit.png); width: 128px; height: 128px;}"
I am aware that something like this is an option:
ui->pushButton_Calibration->setIconSize(QSize(128, 128));
But I am unsure on how to implement this to something with the format QPushButton#pushButton_Calibration or how to use this to implement it globally to the children of my ui element since this syntax directly points to only the element on the particular ui file (at least, this is my understanding).
Please let me know if more information is required to solve this issue. I am unfamiliar with the syntax needed to change the size of the icon and haven't been able to locate it from the documentation.
If you want to set an icon, you should use the icon property, instead of the image property, like this.
QPushButton#pushButton_Calibration {
icon: url(:/images/toolkit.png);
qproperty-iconSize: 128px;
}
And the official documentaion is here.
Also be careful on the scaling of the image. It will not scale up for both 'image' and 'icon' properties.
I would recommend to use QPushButton::setIcon() and QPushButton::setIconSize() member functions instead of working with stylesheets.
One rationale behind this is that once you deal with stylesheets, the system style for the given widget may be completely messed up and you may need to restyle the whole widget even if you only wanted to change a specific part or behaviour.
Per the Qt documentation, you can read the following note regarding the icon property:
"Note: It's the application's responsibility to assign an icon to a button (using the QAbstractButton API), and not the style's. So be careful setting it unless your stylesheet is targeting a specific application."
If you want the change to be applied for all buttons of your application, you can create your own button class that inherits QPushButton and sets the properties you want in the constructor.
Example:
.hpp
class MyButton : public QPushButton
{
Q_OBJECT
public:
MyButton(const QIcon &icon, const QString &text, QWidget *parent = nullptr);
MyButton(const QString &text, QWidget *parent = nullptr);
MyButton(QWidget *parent = nullptr);
};
.cpp
MyButton::MyButton(const QIcon &icon, const QString &text, QWidget *parent) : QPushButton(icon, text, parent)
{
setIconSize({128, 128});
}
MyButton::MyButton(const QString &text, QWidget *parent) : QPushButton(text, parent)
{
setIconSize({128, 128});
}
MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{
setIconSize({128, 128});
}
Of course, you can adapt it to your use case (maybe you want to set the icon inside the constructor as well, etc...)

Accessing widgets inside QStackedWidget

I am developing a Qt app with QtDesigner.
Previously it was quite easy to access specific widgets to do something with them like connecting signals. After I added QStackedWidget I can no longer access specific widgets with something like ui->stack->page1->widget.
Is there a way to do it somehow? Or should I always call findChild method? Or maybe it is possible to at least assign some of the nested widgets in stack widget to properties of the main windwo class?
QStackedWidget provides a method to get child widgets by index, as well as the current widget.
A quick example is as follows:
MOCed Header
class MyWidget: QWidget
{
Q_OBJECT
public:
using QWidget::QWidget
QWidget *ptr;
};
Source File
QStackedWidget *stackedWidget = new QStackedWidget;
stackedWidget->addWidget(new MyWidget); // index 0
stackedWidget->addWidget(new QWidget); // index 1
stackedWidget->addWidget(new MyWidget); // index 2
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(stackedWidget);
setLayout(layout);
// do something specific with the first widget's ptr element
auto* widget = stackedWidget->widget(0);
auto* mywidget = qobject_cast<MyWidget*>(widget);
if (mywidget) {
mywidget->ptr->setObjectName("FirstPage");
}
Now, Qt uses virtual interfaces by default, so if you have a custom subwidget you need to extract, you can use qobject_cast. qobject_cast is basically a fast dynamic_cast, and works even without RTTI. In template-driven code, dynamic_cast is a bit of a code-smell: it means you lost useful type information too early. With virtual interfaces, the exact opposite is true: you should use qobject_cast as needed.
Why you get the widget layer by layer, if your widgets are added in Qt designer, you can get it by ui->widget directly.

Retrieving parent QTableWidget from its cell widget item

I am working on a Project using Qt 5.7 with C++. I am stuck in a weird problem.
I have a QTableWidget which contains a QComboBox on its one and only cell. Simplified code is as follows.
QTableWidget *tab = new QTableWidget();
tab->insertColumn(0);
tab->insertRow(0);
QComboBox *cb = new QComboBox(tab);
cb->addItem("A");
cb->addItem("B");
tab->setCellWidget(0, 0, cb);
Now on currentIndexChanged(int) signal of the QComboBox, I am connecting to a SLOT where I am trying to retrieve the pointer of the QTableWidget as follows,
QComboBox* cb = qobject_cast<QComboBox*>(sender());
QWidget* par = cb->parentWidget();
But, I am not getting the same pointer as the actual QTableWidget.
I have also tried as follows, but still failed.
QComboBox* cb = qobject_cast<QComboBox*>(sender());
QObject *par = cb->parent();
QTableWidget *tab = qobject_cast<QTableWidget *>(par);
Can anyone suggest some other way to do it or point out the error in those code segment ?
Possible Solution Found
Parent Widget can be retrieved using cb->parent()->parent(). Although, this process is not documented, so, not reliable.
The reason is that the QTableWidget is not a direct parent of QComboBox, but a grand parent. But even this is an implementation detail and cannot be relied upon, because it is not documented.
A way out could be storing the QTableWidget pointer somewhere else.

QMenu item text disappears when icon added

I am attempting to add an icon to my QMenu using Qt Designer, however I realized that my text disappears when my icon is added. Is there any way for me to show my icon next to my text?
It was not supported in Qt 4, maybe it is in Qt5 I haven't checked.
In Designer itself there isn't much you can do. In the code one option is to customize the style to draw both the icon and text:
- sizeFromContents for QStyle::CT_MenuBarItem
- drawControl for QStyle::CE_MenuBarItem
- drawCustomControl for QStyleOptionMenuItem
This is not supported by default, mostly because it is not usual an operation that you wish to achieve in here. Of course, you could always use an image with text included, but that is also hackish, unless you paint the image dynamically and then load it later. Although even that would be quite a bit of work.
In order to do, you will need to fiddle with Qt a bit. This is the closest experiment that I would start off with, personally. I have not had time to check whether it actually works, but there should be something among these lines:
class CustomMenuBarWidget : public QWidget
{
public:
explicit CustomMenuBarWidget(QWidget *parent = Q_NULLPTR)
: QWidget(parent)
, menuBar(new QMenuBar())
{
}
virtual void paintEvent(QPaintEvent *event) {
QStyleOptionMenuItem styleOptionMenuItem;
QIcon icon("path/to/my/icon");
styleOptionMenuItem.icon = icon;
styleOptionMenuItem.text = "Hello World!";
QPainter painter(this);
menuBar->style()->drawControl(QStyle::CE_MenuBarItem, &styleOptionMenuItem, &painter, menuBar);
}
private:
QMenuBar *menuBar;
};
You could probably also have a look at QWidgetAction how to insert custom widgets into toolbars and menubars. I have never used that myself in any serious project, but might be useful to be aware of.

Why do we pass "this" pointer to setupUi function?

I'm fairly new in QT. Taking below fairly simply explain from qt docs :
class CalculatorForm : public QWidget
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
private:
Ui::CalculatorForm ui;
};
and implementation of constructor
CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent) {
ui.setupUi(this); // <-- Question below
}
Q: I was wondering why do we pass this pointer to setupUi function?, what does it do ?
So that the dialog will have the caller as parent, so that eg when the parent is closed the dialog can be closed automatically. Generally all gui elements have a pointer to their parent.
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
These are auto generated slots which exactly match the naming of the gui elments in QtDesigner. They are only meant to do the direct hookup to those gui elements and so should be dealt with in this class. If these signals were extended to other classes then any change in the gui would require changing a lot of other code which doesn't need to know details of the gui.
In the handler slot for the specific gui element you can then emit another more general signal to the rest of the app.
The only widget that setupUi doesn't create is the widget at the top of the hierarchy in the ui file, and as the Ui::CalculatorForm class instance doesn't know the widget it has to fill, it (this) has to be passed explicitly to the class at some point.
this or any other widget you would pass to it, is used as the parent to all other subwidgets. For example, you could fill a widget without inheritance like this:
QWidget *widget = new QWidget;
Ui::CalculatorForm *ui = new Ui::CalculatorForm;
ui->setupUi(widget);
widget->show();
But really, it would be easier to understand if you read the content of the uic generated file (probably named ui_calculatorform.h).
setupUi creates the instances of widgets (QLabel, QTextEdit and so on). The [user interface compiler] (http://qt-project.org/doc/qt-4.8/uic.html) gets information for you from the .UI form and generates widget-creation code in the generated moc source files.
The manual way of creating widgets without using the Qt Designer or a UI file would be like so:
QWidget* pWidget = new QWidget(this);
I think it is to add the caller widget to the layout of this UI.
This widget will be the toplevel widget.
Martin Beckett answer might be correct as well, as what he described is a common behavior in Qt (cf the 'parent' argument in most of widget's derived class constructor)
Note that you have alternative ways how designer can auto-generate code.
In this case you have a separate 'UI' class for this code which is not QObject so it also is not a QWidget.
Auto generated code needs information about parent widget and to make auto-conections of slots and signals so this is why you have to pass this.
This pater is less intrusive then other pasterns (that is why it is default). You can also try alternative patters (check Qt Creator Designer options), but I recommend you to see what is generated by designer tools in default settings.