Can not set font-weight for pseudo-states in qt - css

I'm facing a problem in which I want to make the font bold in an QPushButton when it is hovered or pressed. But font-weight property only works in normal state, on font state it doesn't affect anything.
I'm really looking for a solution.

Looks like a bug to me--the style sheet font properties are ignored in the hover state. I was not able to come up with a workaround using style sheets, but you can always subclass QPushButton to get what you need:
#include <QtGui>
class HoverablePushButton : public QPushButton {
public:
HoverablePushButton(const QString &text, QWidget *parent = NULL)
: QPushButton(text, parent) {}
protected:
void enterEvent(QEvent *event) {
QPushButton::enterEvent(event);
QFont f(font());
f.setBold(true);
setFont(f);
}
void leaveEvent(QEvent *event) {
QPushButton::leaveEvent(event);
QFont f(font());
f.setBold(false);
setFont(f);
}
};
int main(int argc, char **argv) {
QApplication app(argc, argv);
HoverablePushButton b("hello!");
b.show();
return app.exec();
}
Might be overkill, but if the functionality is critical for your application, it is at least one workaround.

Related

Is it possible to change default behavior of a checkable QGroupBox?

The question is pretty straight forward: is it possible to change the default behavior of a checkable QGroupBox object? I designed a user interface with many QLineEdit objects inside a checkable QGroupBox, the desired behavior is: when QGroupBox is not checked all of its children are enable and when it is checked all of its children are disable.
As you can see at the oficial QGroupBox documentation, it says:
If the check box is checked, the group box's children are enabled; otherwise, the children are disabled and are inaccessible to the user.
One trick is to modify the painting so that when it is checked the check is not shown and vice versa:
#include <QtWidgets>
class GroupBox: public QGroupBox{
public:
using QGroupBox::QGroupBox;
protected:
void paintEvent(QPaintEvent *){
QStylePainter paint(this);
QStyleOptionGroupBox option;
initStyleOption(&option);
if(isCheckable()){
option.state &= ~(isChecked() ? QStyle::State_On : QStyle::State_Off);
option.state |= (isChecked() ? QStyle::State_Off : QStyle::State_On);
}
paint.drawComplexControl(QStyle::CC_GroupBox, option);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GroupBox groupBox;
groupBox.setCheckable(true);
QVBoxLayout *vbox = new QVBoxLayout;
vbox->addWidget(new QLineEdit);
vbox->addWidget(new QLineEdit);
vbox->addWidget(new QLineEdit);
vbox->addStretch(1);
groupBox.setLayout(vbox);
groupBox.show();
return a.exec();
}

Prevent QApplication app from closing if a service is running

I have a QML app in which I have subclassed QApplication to create my main screen with QML. The issue i have is on clicking Close button the application closes as intended, but I want to handle a situation where if some services are running I want to override close button behaviour.
I tried overriding closeEvent() without any luck. Can anyone point me to some ways I can handle this?
UPDATE : This is the code snippet I tried
class SingleApplication : public QApplication {
Q_OBJECT
public:
SingleApplication(int &argc, char **argv);
void closeEvent ( QCloseEvent * event )
{
event->ignore();
}
}
MAIN.cpp
#include "view.h"
#include <QDebug>
#include <QDesktopWidget>
#include "SingleApplication.h"
int main(int argc, char *argv[])
{
SingleApplication app(argc, argv);
if(!app.isRunning()) {
app.processEvents();
View view(QUrl("qrc:/qml/main.qml"));
#ifdef Q_OS_LINUX
view.setFlags(Qt::WindowMinimizeButtonHint|Qt::WindowCloseButtonHint);
#endif
view.setMaximumSize(QSize(1280,700));
view.setMinimumSize(QSize(1280,700));
// Centering the App to the middle of the screen
int width = view.frameGeometry().width();
int height = view.frameGeometry().height();
QDesktopWidget wid;
int screenWidth = wid.screen()->width();
int screenHeight = wid.screen()->height();
view.setGeometry((screenWidth/2)-(width/2),(screenHeight/2)-(height/2),width,height);
view.show();
return app.exec();
}
return 0;
}
There is no QApplication::closeEvent. Such virtual function belongs to QWidget.
Use of QApplication indicated that you have normal QWidget container for your QML UI (as you say UI is based on QML though). You should rather override that widget closeEvent e.g.:
class MyMainWidget : public QWidget // or is it QMainWindow?
{
// snip
private:
void closeEvent(QCloseEvent*);
}
void MyMainWidget::closeEvent(QCloseEvent* event)
{
// decide whether or not the event accepted
if (condition())
event->accept();
}
And if your container widget is not overridden yet (simply QWidget?), well, now you have to do so.
And you did not say whether or not you want to keep app window running. I assume you want that as well.

App does not close if I set QQuickView-WindowContainer as central widget

My application is designed in that way that different plugins can set the central widget of the main windows to show the desired content.
This works so far.
But if I set a QQuickView-WindowContainer as central widget, the app does not quit when I close the main window.
If I set a "normal" widget like QPushButton as central widget the appliation quits just fine. Why is that?
This is the code of a minimal example which shows this behaviour (MainWindow is a class created from the QtCreator wizard):
class AppCore : public QObject
{
Q_OBJECT
public:
explicit AppCore(QObject *parent = 0);
signals:
public slots:
void showMainWindow();
private:
MainWindow *m_mainWindow;
};
AppCore::AppCore(QObject *parent) :
QObject(parent)
{
}
void AppCore::showMainWindow()
{
QQuickView *view;
QWidget *container;
view = new QQuickView();
container = QWidget::createWindowContainer(view);
view->setSource(QUrl("qrc:/main.qml"));
m_mainWindow = new MainWindow();
//m_mainWindow->setCentralWidget(new QPushButton("Button"));
m_mainWindow->setCentralWidget(container);
m_mainWindow->show();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
AppCore appCore;
appCore.showMainWindow();;
return a.exec();
}
This looks like a bug. I see a dead lock in debugger: v8::internal::RuntimeProfiler::WaitForSomeIsolateToEnterJS and QQmlDataLoader::shutdownThread wait for each other. I can't find a good workaround for this issue.
I found a dirty hack that solved the issue. If container is deleted a bit earlier, all works ok:
void MainWindow::closeEvent(QCloseEvent *e) {
QMainWindow::closeEvent(e);
if (e->isAccepted() && centralWidget()) {
delete centralWidget();
}
}
You probably should send a bug report. Note that m_mainWindow is not needed to reproduce the issue. Using container->show(); gives the same result.

Qt : Child graphic items hover event

I have two items of type QGraphicsRectItem. One over the other.
The first one is a custom class called Wall. Inside the wall there are windows and doors.
In fact, i have a list of Doors and Windows inside this custom Wall class.
The Doors are Items too, and are drawn inside the wall.
When i move the mouse over the door, the hover function of the wall is emited, but the hover of the door is not. Both of them correctly copied one from each other as virtual void protected.
Why is that happening? How can i make the door and window items realize about the hover?.
I have tried with a custom QGraphicsItem instead of a custom QGraphicsRectItem. It seems the hover event handler is successfully called for both Wall and Door. This is happening when explicitly setting QGraphicsItem with setAcceptHoverEvents(true). This is not tested with custom QGraphicsRectItem.
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QPainter>
class Item : public QGraphicsItem
{
QBrush m_brush;
public:
explicit Item(bool nested = true, QGraphicsItem* parent = 0) : QGraphicsItem(parent), m_brush(Qt::white)
{
if (nested) {
Item* item = new Item(false, this);
item->setPos(10,10);
m_brush = Qt::red;
}
setAcceptHoverEvents(true);
}
QRectF boundingRect() const
{
return QRectF(0,0,100,100);
}
void hoverEnterEvent(QGraphicsSceneHoverEvent *)
{
m_brush = Qt::red;
update();
}
void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
{
m_brush = Qt::white;
update();
}
void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
{
p->setBrush(m_brush);
p->drawRoundRect(boundingRect());
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene scene;
scene.addItem(new Item);
QGraphicsView view;
view.setScene(&scene);
view.setMouseTracking(true);
view.show();
return app.exec();
}

QDialog with transparent background color

I want to make the background of a QDialog transparent so that I can see through the window. I'm asking because I want to use a semi-transparent background image that creates a "rounded corner window" illusion. Using setOpacity is not an option for me because I want all widgets to remain at full opacity.
Is there a way to achieve this without resorting to native OS APIs?
Use QWidget::setAttribute(Qt::WA_TranslucentBackground);. Note that this also requires Qt::FramelessWindowHint to be set.
This example works for me:
#include <QtGui>
class Dialog : public QDialog
{
public:
Dialog() : QDialog(0, Qt::FramelessWindowHint) // hint is required on Windows
{
QPushButton *button = new QPushButton("Some Button", this);
setAttribute(Qt::WA_TranslucentBackground);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog d;
d.show();
return a.exec();
}
Regarding rounded corners, QWidget::setMask() will help you.
EDIT: In response to another question below in the comments, here is a working example that uses an image in a resources file, and that overrides QWidget::paintEvent():
#include <QtGui>
class Dialog : public QDialog
{
public:
Dialog() : QDialog(0, Qt::FramelessWindowHint) // hint is required on Windows
{
setFixedSize(500, 500); // size of the background image
QPushButton *button = new QPushButton("Some Button", this);
setAttribute(Qt::WA_TranslucentBackground);
}
protected:
void paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawImage(QRectF(0, 0, 500, 500), QImage(":/resources/image.png"));
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog d;
d.show();
return a.exec();
}

Resources