QMenu change background color - qt

I'm trying to change the background color of a QMenu* object it does not work with setStyleSheet(), nor with setPalette().
I read this article but the guy says that I should add this line:
app.setStyle(QStyleFactory::create("fusion"));
I'm not sure what is app, I tried several combinations but it does not work.
Thanks!

You probably forgot to set QMenu's parent:
#include <QtGui>
class Window : public QWidget
{
public:
Window(QWidget *parent = 0) : QWidget(parent) {}
void contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
menu.addAction(new QAction("Item 1", this));
menu.addAction(new QAction("Item 2", this));
menu.exec(event->pos());
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window *window = new Window;
window->setStyleSheet("QMenu::item:selected { background-color: green; }");
window->show();
return app.exec();
}

Related

Virtual keyboard or onscreen keyboard for QtWidgets applications?

I'm going to deploy the qtvirtualkeyboard in my widget-based application like so:
#include <QtWidgets>
int main(int argc, char *argv[]) {
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QApplication app(argc, argv);
QMainWindow window;
QLineEdit input(&window);
input.move(250, 250);
window.show();
return app.exec();
}
But the only issue is that the virtual keyboard input panel hides the underlying widgets and cover them!
How should I achieve this?
Is there any document or solution for widgets-based applications?
you just need to add this line in main.cpp
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
and will work Virtual Keyboard in Qtwidgets))
Finally got the solution!
You just need to call QGuiApplication::inputMethod() to get the application-wide Qt input method and then call QInputMethod::keyboardRectangle() and QInputMethod::isVisible() to get input method properties then remain a calculation based on your widget position and keyboard coordinate, here is a full-working sample to share:
lineedit.h:
class LineEdit :public QLineEdit {
Q_OBJECT
public:
LineEdit(QWidget *parent = nullptr);
LineEdit(const QString&, QWidget *parent = nullptr);
protected:
bool event(QEvent*) override;
private:
bool _moved = false;
int _lastDiff = 0;
};
lineedit.cpp:
LineEdit::LineEdit(QWidget *parent) :QLineEdit(parent) {
setAttribute(Qt::WA_InputMethodEnabled, true);
setInputMethodHints(inputMethodHints() | Qt::InputMethodHint::ImhDigitsOnly);
}
LineEdit::LineEdit(const QString& txt, QWidget *parent) : QLineEdit(txt, parent) {
setAttribute(Qt::WA_InputMethodEnabled, true);
setInputMethodHints(inputMethodHints() | Qt::InputMethodHint::ImhDigitsOnly);
}
bool LineEdit::event(QEvent* e) {
const auto keyboard_rect = QGuiApplication::inputMethod()->keyboardRectangle();
const auto keyboard_visible = QGuiApplication::inputMethod()->isVisible();
const auto global_y = QWidget::mapToGlobal(rect().topLeft()).y() + height();
const auto k_global_y = keyboard_rect.topLeft().y();
const auto diff = k_global_y - global_y;
const auto need_to_move = diff < 0;
/* move main widget */
if (keyboard_visible && !_moved && need_to_move) {
_moved = true;
_lastDiff = diff;
const auto g = parentWidget()->frameGeometry();
parentWidget()->move(g.x(), g.y() - qAbs(_lastDiff));
}
/* roll back */
if (!keyboard_visible && _moved) {
_moved = false;
const auto g = parentWidget()->frameGeometry();
parentWidget()->move(g.x(), g.y() + qAbs(_lastDiff));
}
return QLineEdit::event(e);
}
main.cpp:
#include <QtWidgets>
#define W 1024
#define H 768
int main(int argc, char *argv[]) {
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QApplication app(argc, argv);
QMainWindow window(nullptr, Qt::FramelessWindowHint);
LineEdit lineedit1(&window);
lineedit1.move(100, 450);
LineEdit lineedit2(&window);
lineedit2.move(100, 100);
window.resize(W, H);
window.show();
return app.exec();
}
results:

QWidget::show() with a set parent

Is it expected behaviour that QDialog::show() does not show the window if a parent has been set?
Background: I want to use QMetaObject::connectSlotsByName() to react to one of the dialogs signals, which means the parent-object needs to own it. Without the line marked as "This is the line in question" I get a runtime-message "QMetaObject::connectSlotsByName: No matching signal for on_child_accepted()". But with the line, the child dialog no longer appears.
#include <QtCore/QDebug>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
class Parent : public QDialog
{
Q_OBJECT
public:
Parent(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
: QDialog{parent, f}
{
b.setText(tr("Show child"));
connect(&b, &QPushButton::clicked, [&]() {
c.show();
});
l.addWidget(&b);
setLayout(&l);
c.setParent(this); // This is the line in question
c.setObjectName("child");
QMetaObject::connectSlotsByName(this);
}
private slots:
void on_child_accepted()
{
qDebug() << "I got called";
}
private:
QPushButton b;
QDialog c;
QVBoxLayout l;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Parent w;
w.show();
return a.exec();
}
This test fails on Qt 5.11 for Windows, from the MSYS2 64-bit build.
Any suggestions? Thank you in advance.
The dialog did actually appear, but not where you think it did: it is a non-window child widget of your window - it was transparent and yet it obscured most of the "Show Dialog" button, consuming all mouse events, and furthermore it was already shown since all children are shown when the parent is shown - so the button appeared to be non-functional for both of those reasons.
Setting a widget's parent clears its Qt::Window flag. Setting the dialog's background helps visualize the problem. Thus, you need to make the dialog a window after setting its parent.
The following reproduces your bug, and also demonstrates the fix.
// https://github.com/KubaO/stackoverflown/tree/master/questions/dialog-show-parenting-53208641
#include <QtWidgets>
class Parent : public QDialog {
Q_OBJECT
QVBoxLayout layout{this};
QDialog child;
QPushButton cShow{tr("Show child")}, cNonWindow{tr("Renew non-window child")},
cWindow{tr("Renew window child")};
Q_SLOT void on_child_accepted() {}
void reChild(bool makeWindow) {
child.~QDialog();
new (&child) QDialog;
Q_ASSERT(child.isWindow());
child.setParent(this);
child.setObjectName("child");
child.setStyleSheet("QWidget { background: blue }");
if (makeWindow) {
child.setWindowFlag(Qt::Dialog);
Q_ASSERT(child.isWindow());
} else {
Q_ASSERT(!child.isWindow());
child.show(); // The child gets shown when we're shown
}
QMetaObject::invokeMethod(this, &Parent::updateChild, Qt::QueuedConnection);
}
void updateChild() {
if (!child.isWindow()) child.move(50, cWindow.y() + cWindow.height() / 2);
this->update(); // Work around a refresh bug (affects OS X on 5.11 at least)
}
public:
Parent(QWidget *parent = nullptr, Qt::WindowFlags f = {}) : QDialog{parent, f} {
connect(&cShow, &QPushButton::clicked, [&]() { child.show(); });
connect(&cNonWindow, &QPushButton::clicked, [&] { reChild(false); });
connect(&cWindow, &QPushButton::clicked, [&] { reChild(true); });
for (auto *w : {&cShow, &cNonWindow, &cWindow}) layout.addWidget(w);
cNonWindow.click();
QMetaObject::connectSlotsByName(this);
}
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Parent w;
w.show();
return a.exec();
}
#include "main.moc"

how to clickable a QGraphicsTextItem?

I have a QDialog for beginning of my game.in this class I have a QGraphicsTextItem. I want to it is clickable. When user clicked play game start. I do this but not work.
class Mydialog_start:public QDialog
{
Q_OBJECT
public:
explicit Mydialog_start(QWidget *parent = 0);
signals:
public slots:
void on_play_clicked();
void on_exit_clicked();
private:
QGraphicsScene* scene;
QGraphicsView* view;
QPixmap image;
QBrush brush;
QGraphicsTextItem* text;
QFont font;
const int x_size;
const int y_size;
};
Mydialog_start::Mydialog_start(QWidget *parent) :
QDialog(parent),x_size(400),y_size(400)
{
scene=new QGraphicsScene(this);
view=new QGraphicsView(this);
view->setScene(scene);
scene->setSceneRect(0,0,x_size,y_size);
image.load(":picture/image/background.jpg");
image=image.scaled(x_size,y_size);
brush.setTexture(image);
scene->setBackgroundBrush(brush);
font.setBold(true);
font.setPointSize(40);
font.setItalic(true);
text=scene->addText("play",font);
text->setDefaultTextColor(QColor("red"));
text->setPos(100,300);
this->setFixedSize(400,400);
connect(text,SIGNAL(linkActivated(QString("play"))),this,SLOT(on_play_clicked()));
}
void Mydialog_start::on_play_clicked()
{
accept();
}
void Mydialog_start::on_exit_clicked()
{
reject();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
Mydialog_start dialog;
dialog.exec();
if( dialog.exec()==QDialog::Accepted)
{
w.show();
}
else
{
w.close();
}
}
Not quite sure whether you needed your text item to be "editable" - see Mitch's comment...
It seems that you need your item to be "clickable" - then all you need are some flags:
text->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);

Qt Widget temporarily fullscreen

Consider a QWidget, normally a child in some Layout.
Supposed I want to make it fullScreen for a while, then have it return to it's old spot.
QWidget::setFullScreen() requires that the widget needs to be an independent window - any ideas how to work it out?
The simplest way I can see is to reparent to 0. Something like this:
#include <QApplication>
#include <QPushButton>
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent) : QPushButton(parent) {}
void mousePressEvent(QMouseEvent*) {
this->setParent(0);
this->showMaximized();
this->show();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget mainWidget;
MyButton button(&mainWidget);
mainWidget.show();
return a.exec();
}
I have modified the previous example. The previous example never goes back to normal screen.
Just copy paste the code and it will run.
#include <QApplication>
#include <QPushButton>
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent) : QPushButton(parent) {
m_pParent = parent;
maxMode = false;
}
QWidget * m_pParent;
bool maxMode;
Qt::WindowFlags m_enOrigWindowFlags;
QSize m_pSize;
void mousePressEvent(QMouseEvent*) {
if (maxMode== false)
{
m_enOrigWindowFlags = this->windowFlags();
m_pSize = this->size();
this->setParent(0);
this->setWindowFlags( Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
this->showMaximized();
maxMode = true;
}
else
{
this->setParent(m_pParent);
this ->resize(m_pSize);
this->overrideWindowFlags(m_enOrigWindowFlags);
this->show();
maxMode = false;
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget mainWidget;
MyButton button(&mainWidget);
mainWidget.show();
return a.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