LINUX.ORG.RU

Сообщения le_poisson

 

Пропуск QMouseEvent и QKeyPressEvent через QMdiArea

Для моего проекта мне нужна возможность создавать меньшие окна внутри основного окна. После прочтения документации, я нашел нативную их имплементацию - QMdiSubWindow.

Однако, у меня возникли проблемы с QMdiArea. Для начала, она по умолчанию непрозрачна, однако я легко смог решить это через прозрачную кисть:

subwindowArea->setBackground(QBrush(QColor(0, 0, 0, 0)));

Трудности начались дальше - QMdiArea не пропускает QEvent-ы на нижние виджеты, что в принципе ожидаемо.

Сначала я пробовал задать QMdiArea как центральный виджет с остальным интерфейсом в качестве детей. Не сработало, т.к. вторичные окна стали загружаться под виджетом камеры, блокируясь таким образом из вида.

Затем я ввел QMdiArea атрибут на прозрачность для мыши, однако после этого я уже не смог взаимодействовать (перемещать, закрывать) с тестовым вторичным окном.

subwindowArea->setAttribute( Qt::WA_TransparentForMouseEvents );

Ситуация осложняется еще и тем, что QMdiSubWindow - неполный класс и я не могу создавать его экземпляры или кастовать в него напрямую.

Я хочу узнать, есть ли способ сделать QMdiArea прозрачной для QEvent - ов за исключением того, когда одно из окон в фокусе (кроме того, что при каждом mouseevent-e проверять курсор на расположении в каждом из окон, хотя тут тоже придется извернуться кастуя их к QWidget-у), или какой-либо другой способ создания окон внутри окон в рамках фреймворка Qt.

 , ,

le_poisson
()

Тип layout-а в QMainWindow->layout()

Если кратко, то я решил написать средней простенькости игру на Qt и поначалу для динамического добавления виджетов просто пихал их в layout основного окна:

    // Dynamically add widgets layer by layer
    this->layout()->addWidget(gameSingleton->getCamera());

    for(auto widget : gameSingleton->getBackgroundWidgets()){
         this->layout()->addWidget(widget);
    }

    for(auto widget : gameSingleton->getForegroundWidgets()){
         this->layout()->addWidget(widget);
    }

Это вызывало предупреждения при запуске, да и я сам решил переделать это дело таким образом, чтобы я мог передавать виджет, к которому будет прикреплен интерфейс, по указателю. И тут начинается самое интересное. У базового centralWidget-а создаваемого в gamewindow.ui layout не задан, нижеприведенный код сегфолтится:

    // Dynamically add widgets layer by layer
this->centralWidget()->layout()->addWidget(gameSingleton->getCamera());

    for(auto widget : gameSingleton->getBackgroundWidgets()){
         this->centralWidget()->layout()->addWidget(widget);
    }

    for(auto widget : gameSingleton->getForegroundWidgets()){
         this->centralWidget()->layout()->addWidget(widget);
    }

Если затать ему layout или свой центральный виджет, то ни QHBoxLayout,ни QStackedLayout, ни QGridLayout не соответствуют тому, что ранее был в QMainWindow, либо перемешивая все виджеты в соответствии со своим шаблоном, либо ставя один из них поверх остальных.

Меня интересует, есть ли в Qt потомок QLayout который бы просто расставлял помещенные в него виджеты по своим координатам, не группируя их в клетки, колонны и прочего ненужного мне функционала? В идеале бы именно тот, который используется в QMainWindow.

 , ,

le_poisson
()

Type casting в c++.

Сегодня столкнулся с тем, что для моего проекта на плюсах просто необходимо преобразование типов как вверх, так и вниз (большая часть объектов хранится в одном stl контейнере, хранящем указатели имеющие тип интерфейса, от которого наследуется добрая половина всего, без кастования типов пришлось бы переносить некоторый функционал в сам интерфейс, а это еще больший говнокод)

Допустим, у нас есть такой код.

// Предположим,что класс Foo абстрактный                    
// (иначе downcast попросту невозможен)

class Foo {
   // какая-то переменная
   SomeType something;
   // что-то еще
public:
   // меняем вышеназванную переменную
   virtual void setSomething(SomeType newSomething);
   // что-то еще
};

class Bar : public Foo{
   // что-то
public:
   void setSomething(SomeType newSomething) override;
   // получаем значение 
   SomeType getSomething();
};

int main(){
   // создаем указатель, выделяем память и задаем параметр
   Bar * somepointer_a = new bar;
   somepointer_a->setSomething(SomeType alpha);
   //Создаем новый указатель с типом родительского класса через \
   //кастование типов
   Foo * somepointer_b = dynamic_cast<Foo*>(someponter_a);
   //Используем  функцию, которая была оверрайднута
   somepointer_b->setSomething(SomeType beta);
   //Создаем указатель изначального типа и получаем значение
   Bar * somepointer_c = dynamic_cast<Bar*>(someponter_b);
   std::cout << somepointer_c->getSomething();
}

Есть ли вероятность, что на stdout выведет не то, что было в beta, а то что было в alpha или вообще вылетит с ошибкой? А если еще конктретнее, можно ли это считать неопределенным поведением и способна ли последовательность из upcast и downcast привести к потере данных?

 

le_poisson
()

RSS подписка на новые темы