Russian Qt Forum
Ноябрь 26, 2024, 16:23 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: [РЕШ.] QMessageBox. Крэш при установке пользовательского размера окна (Qt 5.2.1)  (Прочитано 16612 раз)
Fuzzy Barsik
Гость
« : Февраль 21, 2014, 00:25 »

Добрый день всем!

Поскольку я только-только начал знакомиться с Qt, неудивительно, что у меня с ним много проблем, - не бейте сильно, пожалуйста, если что...

Я пытаюсь задать пользовательский стиль окнам QMessageBox, которые появляются при выборе пунктов меню (например, при выборе пункта Updates...), и в первую очередь - задать адекватный размер, поскольку подгоняемые системой размеры под размер текста - слишком маленькие. Поскольку setFixedSize() и другие подобные манипуляции по какой-то причине не работают, я пытаюсь использовать костыли вот отсюда. Вот код:

fuzzygui.cpp
Код
PHP
#include "fuzzygui.h"
#include "ui_fuzzygui.h"
 
#include <QMessageBox>
#include <QSpacerItem>
#include <QGridLayout>
 
FuzzyGUI::FuzzyGUI(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::FuzzyGUI)
{
   ui->setupUi(this);
}
 
FuzzyGUI::~FuzzyGUI()
{
   delete ui;
}
 
void FuzzyGUI::on_actionExit_triggered()
{
   qApp->quit();
}
 
void FuzzyGUI::on_actionUpdates_triggered()
{
   QMessageBox updateOptions;
   updateOptions.setWindowTitle(tr("Update Checker"));
   updateOptions.setIcon(QMessageBox::Question);
   updateOptions.setText(tr("Are you sure there will be any updates?"));
   updateOptions.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
   updateOptions.setDefaultButton(QMessageBox::No);
 
   // Workaround for setting QMessageBox size //
   QSpacerItem* horizontalSpacer = new QSpacerItem(300, 100, QSizePolicy::Fixed, QSizePolicy::Fixed);
   QGridLayout* layout = (QGridLayout*)updateOptions.layout();
   layout->addItem(horizontalSpacer, 0, 0, 0, 0);
 
   int userChoice = updateOptions.exec();
 
   QMessageBox choiceConfirmation;
   choiceConfirmation.setWindowTitle(tr("Update Checker"));
   choiceConfirmation.setIcon(QMessageBox::Information);
   choiceConfirmation.setStandardButtons(QMessageBox::Ok);
   if (userChoice == QMessageBox::Yes) {
       choiceConfirmation.setText(tr("Wrong guess"));
   } else {
       choiceConfirmation.setText(tr("That is correct"));
   }
 
   // Workaround for setting QMessageBox size //
   layout = (QGridLayout*)choiceConfirmation.layout();
   layout->addItem(horizontalSpacer, 0, 0, 0, 0);
 
   choiceConfirmation.exec();
}

fuzzygui.h
Код
PHP
#ifndef FUZZYGUI_H
#define FUZZYGUI_H
 
#include <QMainWindow>
 
namespace Ui {
class FuzzyGUI;
}
 
class FuzzyGUI : public QMainWindow
{
   Q_OBJECT
 
public:
   explicit FuzzyGUI(QWidget *parent = 0);
   ~FuzzyGUI();
 
private slots:
   void on_actionExit_triggered();
 
   void on_actionUpdates_triggered();
 
private:
   Ui::FuzzyGUI *ui;
};
 
#endif // FUZZYGUI_H

main.cpp
Код
PHP
#include "fuzzygui.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   FuzzyGUI w;
   w.show();
 
   return a.exec();
}

Нужный размер, безусловно, устанавливается, но как только я нажимаю на кнопку во втором окне, программа падает... При этом всё нормально работает, если размер окон менять не пытаться...

Буду признателен, если кто-либо поможет проблему разрешить. Если есть более простое решение, возможно, с использованием других классов, буду признателен за подсказку.

С компиляцией проектов на моей сборке Qt (официальная сборка Qt 5.2.1 for Windows 64-bit VC 2012 (ANGLE)) изначально были проблемы. Влияет ли это как-то на нынешние падения, я не знаю...

Также хотелось бы понять, как полностью избавиться в QMessageBox от иконки в заголовке окна и как задать нужный мне цвет фона (сейчас появляется системное окно, разделённое на две части: один цвет в верхней части окна с текстом и другой цвет в нижней с кнопками).


Заранее признателен.
« Последнее редактирование: Февраль 22, 2014, 09:35 от Fuzzy Barsik » Записан
Bepec
Гость
« Ответ #1 : Февраль 21, 2014, 00:40 »

На первый взгляд тут опасно
Код:
   layout = (QGridLayout*)ch
Вы преобразовываете сишно и не проверяете результата. Вообще там может мусор быть.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #2 : Февраль 21, 2014, 02:45 »

по-моему проще свой диалог написать, чем вставлять всякие грязные хаки, раз QMessageBox сильно не устраивает

иконку наверное можно убрать только через WinAPI
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Bepec
Гость
« Ответ #3 : Февраль 21, 2014, 12:08 »

setIcon(QIcon()) ? Улыбающийся
Записан
Fuzzy Barsik
Гость
« Ответ #4 : Февраль 21, 2014, 13:26 »

Вы преобразовываете сишно и не проверяете результата.
Э-э-э... Это не я, это автор костыля - я до этого ещё вообще не дорос...
Преобразование вида QGridLayout* layout = const_cast<QGridLayout*>(updateOptions.layout()); выдаёт ошибку компилятора: "C2440: 'const_cast' : cannot convert from 'QLayout *' to 'QGridLayout *' Conversion from pointer to base class to pointer to derived class requires an explicit cast (other than const_cast)".

Если вместо const использовать другие преобразования - крэш.
Если вместо QGridLayout задать QLayout, невозможно отформатировать расположение добавляемого QSpacerItem, бо на поверку оказывается, что стиль окна - это всё же Grid, и в итоге всё равно крэш.

setIcon(QIcon()) ? Улыбающийся
А разве setIcon() у QMessageBox как-то влияет на иконку окна? Или я совсем безнадёжен?

по-моему проще свой диалог написать, чем вставлять всякие грязные хаки, раз QMessageBox сильно не устраивает
Наверное, Вы правы.

З.Ы. Пошёл читать книжки...
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #5 : Февраль 21, 2014, 13:44 »

А разве setIcon() у QMessageBox как-то влияет на иконку окна?

Неверный совет. http://qt-project.org/doc/qt-4.8/qwidget.html#windowIcon-prop
Записан
Bepec
Гость
« Ответ #6 : Февраль 21, 2014, 14:18 »

Каюсь, не дочитал ТС-са, думал об внутриоконной иконке речь.
А на окне будет иконка родительского окна.
Записан
Fuzzy Barsik
Гость
« Ответ #7 : Февраль 21, 2014, 19:15 »

Крэш победил путём повторного создания QSpacerItem для второго окна.
Поигрался с setWindowIcon() и setWindowFlags(). Код сейчас выглядит как-то так:
Код
PHP
#include "fuzzygui.h"
#include "ui_fuzzygui.h"
 
#include <QGridLayout>
#include <QMessageBox>
#include <QPixmap>
#include <QSpacerItem>
 
FuzzyGUI::FuzzyGUI(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::FuzzyGUI)
{
   ui->setupUi(this);
}
 
FuzzyGUI::~FuzzyGUI()
{
   delete ui;
}
 
void FuzzyGUI::on_actionExit_triggered()
{
   qApp->quit();
}
 
void FuzzyGUI::on_actionUpdates_triggered()
{
   QMessageBox updateOptions;
   updateOptions.setWindowTitle(tr("Update Checker"));
   updateOptions.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
   updateOptions.setIcon(QMessageBox::Question);
   updateOptions.setText(tr("Are you sure there will be any updates?"));
   updateOptions.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
   updateOptions.setDefaultButton(QMessageBox::No);
 
   // Workaround for setting QMessageBox size //
   QSpacerItem* horizontalSpacer = new QSpacerItem(300, 100, QSizePolicy::Fixed, QSizePolicy::Fixed);
   dynamic_cast<QGridLayout*>(updateOptions.layout())->addItem(horizontalSpacer, 0, 0, 0, 0);
 
   int userChoice = updateOptions.exec();
 
   QPixmap invisibleIcon = QPixmap(1, 1);
 
   QMessageBox choiceConfirmation;
   choiceConfirmation.setWindowTitle(tr("Update Checker"));
   choiceConfirmation.setWindowIcon(QIcon(invisibleIcon));
   choiceConfirmation.setIcon(QMessageBox::Information);
   choiceConfirmation.setStandardButtons(QMessageBox::Ok);
   if (userChoice == QMessageBox::Yes) {
       choiceConfirmation.setText(tr("Wrong guess"));
   } else {
       choiceConfirmation.setText(tr("That is correct"));
   }
 
   // Workaround for setting QMessageBox size //
   horizontalSpacer = new QSpacerItem(300, 100, QSizePolicy::Fixed, QSizePolicy::Fixed);
   dynamic_cast<QGridLayout*>(choiceConfirmation.layout())->addItem(horizontalSpacer, 0, 0, 0, 0);
 
   choiceConfirmation.exec();
}
В случае с setWindowFlags() вариантов, почему-то, получается всего два: либо не иметь иконки окна и кнопки "Закрыть", либо иметь и то, и другое. Иметь кнопку "Закрыть" и не иметь иконки окна по какой-то причине не можно...

В случае с setWindowIcon() иконку-невидимку создать, вроде, можно, но на её месте остаётся "дыра"...

Буржуазные разработчики при этом не стесняются демонстрировать нам своё превосходство в этом вопросе, как-бы вопрошая: "А что можете противопоставить нам вы, советские учёные?"
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #8 : Февраль 21, 2014, 22:12 »

наследник QDialog с аналогичным функционалом пишется быстрее и чище

разве гуй MPC-HC написан на Qt?
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Fuzzy Barsik
Гость
« Ответ #9 : Февраль 21, 2014, 22:17 »

разве гуй MPC-HC написан на Qt?
Нет. Это просто пример.

наследник QDialog с аналогичным функционалом пишется быстрее и чище
Убрать иконку я и в QDialog не смог.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #10 : Февраль 21, 2014, 23:29 »

в документации написано, что кнопка закрытия не может существовать без иконки системного меню на некоторых платформах (видно винда — одна из них). остается разве что лезть в WinAPI
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Fuzzy Barsik
Гость
« Ответ #11 : Февраль 21, 2014, 23:36 »

Возможно. Вопрос только в том, что MPC Home Cinema - не единственное приложение, в котором модальные окна имеют кнопку "Закрыть", но не имеют иконки окна. Фактически, стандартом как раз и является окно с кнопкой, но без иконки. Всё это в Windows.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #12 : Февраль 22, 2014, 01:39 »

скорее всего эти приложения рисуются нативными средствами ОС, поэтому
остается разве что лезть в WinAPI

P.S. обратимся к исходникам:
Код
C++ (Qt)
void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
{
...
   if (flags & Qt::CustomizeWindowHint) {
       // modify window flags to make them consistent.
       // Only enable this on non-Mac platforms. Since the old way of doing this would
       // interpret WindowSystemMenuHint as a close button and we can't change that behavior
       // we can't just add this in.
#ifndef Q_WS_MAC
       if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) {
           flags |= Qt::WindowSystemMenuHint;
#else
       if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint
                    | Qt::WindowSystemMenuHint)) {
#endif
           flags |= Qt::WindowTitleHint;
           flags &= ~Qt::FramelessWindowHint;
       }
   } else if (customize && !(flags & Qt::FramelessWindowHint)) {
       // if any of the window hints that affect the titlebar are set
       // and the window is supposed to have frame, we add a titlebar
       // and system menu by default.
       flags |= Qt::WindowSystemMenuHint;
       flags |= Qt::WindowTitleHint;
   }
}
« Последнее редактирование: Февраль 22, 2014, 01:46 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Fuzzy Barsik
Гость
« Ответ #13 : Февраль 22, 2014, 08:43 »

Ну, вот и вопрос, зачем в Qt реализовано именно так...
В дефолтное окно MessageBox в МелкоSoft Visual Studio системное меню (иконку) принудительно не суют:
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #14 : Февраль 22, 2014, 14:55 »

оказывается надо было просто загуглить, первые же ссылки дают ответ:
http://stackoverflow.com/questions/1235812/qt-dialog-with-no-window-icon-system-menu
http://qt-project.org/wiki/Remove_the_System_Menu_of_a_QDialog_on_Windows
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.365 секунд. Запросов: 23.