Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: kadr от Январь 22, 2010, 09:54



Название: Список окон
Отправлено: kadr от Январь 22, 2010, 09:54
Привет всем, скажите как можно сделать так, что бы можно было видеть список всех открытых в данный момент окон!
Есть основное окно, в котором открываются окна, если окно открыто, но не в фокусе, то оно уходит на задний план, за основное окно, которое на весь экран и, которое нельзя свернуть(так надо), так вот надо сделать что бы при нажатии правой кнопкой мыши выпадало контекстное меню в котором был список всех открытых окон, и при нажатии на строку в меню с названием окна, оно становилось активным и соответственно получало фокус!
Что сделал: сделал контекстное меню!  


Название: Re: Список окон
Отправлено: BRE от Январь 22, 2010, 10:01
Если используется QMdiArea, то есть:
QList<QMdiSubWindow *> QMdiArea::subWindowList ( WindowOrder order = CreationOrder ) const

Если используются окна верхнего уровня, то:
QWidgetList QApplication::topLevelWidgets ()   [static]


Название: Re: Список окон
Отправлено: kadr от Январь 22, 2010, 10:26
Если используются окна верхнего уровня, то:
QWidgetList QApplication::topLevelWidgets ()   [static]
А можно поточнее, как этим пользоваться?


Название: Re: Список окон
Отправлено: kadr от Январь 22, 2010, 10:37
Я делаю вот так:
Код:
void nozologia::menu()
{
    int i = 0;
    QMenu *contextMenu = new QMenu;
    contextMenu->addAction("Ввод рецепта");
    contextMenu->addAction("РР-1 Отчет");
    contextMenu->addAction("РЛ-1 Отчет");
    contextMenu->addSeparator();
    contextMenu->addAction("Выход");
    contextMenu->addSeparator();  
    contextMenu->setGeometry(QCursor::pos().x(),QCursor::pos().y(),contextMenu->sizeHint().width(),contextMenu->sizeHint().height());
    contextMenu->show();
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(exit(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(vvod(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(pp1(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(pl1(QAction*)));

    while (i != QApplication::topLevelWidgets().count())
    {
        if (QApplication::topLevelWidgets().value(i)->windowTitle() != "" && QApplication::topLevelWidgets().value(i)->windowTitle() != "7 Нозологий"  && QApplication::topLevelWidgets().value(i)->isVisible())
        {
             contextMenu->addAction(QApplication::topLevelWidgets().value(i)->windowTitle());
        }
        i++;
    }
}
В меню добавляются окна, которые не на переднем плане! Как теперь можно сделать так что бы при нажатии на его название оно переходило на передний план.


Название: Re: Список окон
Отправлено: BRE от Январь 22, 2010, 10:43
А что говорит поиск по форуму?  ;)
http://www.prog.org.ru/topic_7821_0.html


Название: Re: Список окон
Отправлено: DS_tm от Январь 22, 2010, 10:47
Переопределяете в виджите, на котором нужно контекстное меню функцию contextMenuEvent. В ней пишете что-то типа этого:

Код
C++ (Qt)
   QMenu menu;
   foreach (QWidget *w, QApplication::topLevelWidgets()) {
       menu.addAction(w.windowTitle(), this, SLOT(showWidget())).setData(w);
   }
   menu.exec();
 

Создаете приватный слот showWidget, в этом классе с текстом:

Код
C++ (Qt)
   QAction *action = static_const<QAction*> (sender);
   if (action) {
        QWidget *w= static_const<QWidget*>(action->data().toInt());
        if (w) w->show();
   }
 

Код не проверял, мог напартачить с привиденьями, будте внимательным.


Название: Re: Список окон
Отправлено: kadr от Январь 22, 2010, 11:17
Переопределяете в виджите, на котором нужно контекстное меню функцию contextMenuEvent. В ней пишете что-то типа этого:

Код
C++ (Qt)
   QMenu menu;
   foreach (QWidget *w, QApplication::topLevelWidgets()) {
       menu.addAction(w.windowTitle(), this, SLOT(showWidget())).setData(w);
   }
   menu.exec();
 

Создаете приватный слот showWidget, в этом классе с текстом:

Код
C++ (Qt)
   QAction *action = static_const<QAction*> (sender);
   if (action) {
        QWidget *w= static_const<QWidget*>(action->data().toInt());
        if (w) w->show();
   }
 

Код не проверял, мог напартачить с привиденьями, будте внимательным.
А что такое sender, где я должен его определить.
Код:
void nozologia::menu()
{
    int i = 0;


    QMenu *contextMenu = new QMenu;
    contextMenu->addAction("Ввод рецепта");
    contextMenu->addAction("РР-1 Отчет");
    contextMenu->addAction("РЛ-1 Отчет");
    contextMenu->addSeparator();
    contextMenu->addAction("Выход");
    contextMenu->addSeparator();  
    contextMenu->setGeometry(QCursor::pos().x(),QCursor::pos().y(),contextMenu->sizeHint().width(),contextMenu->sizeHint().height());
    contextMenu->show();
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(exit(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(vvod(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(pp1(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(pl1(QAction*)));

    foreach (QWidget *m, QApplication::topLevelWidgets())
    {
        if (m->windowTitle() != "" && m->windowTitle() != "7 Нозологий" && m->isVisible())
        {
            contextMenu->addAction(m->windowTitle(), this, SLOT(showWidget()))->setData(m);
        }      
    }
    contextMenu->exec();

}
и приватный слот
Код:
void nozologia::showWidget(QString *act)
{
    QAction *action = static_cast<QAction*>(sender);

    if (action)
        {
             QWidget *m= static_cast<QWidget*>(action->data().toInt());
             if (m) m->show();
        }
}
Ошибки:
Код:
'QVariant::QVariant(void*)' is private
within this context
invalid static_cast from type '<unresolved overloaded function type>' to type 'QAction*'
nvalid static_cast from type 'int' to type 'QWidget*'


Название: Re: Список окон
Отправлено: kadr от Январь 22, 2010, 11:27
Добавил в
contextMenu->addAction(m->windowTitle(), this, SLOT(showWidget()))->setData(m);
windowTitle();
contextMenu->addAction(m->windowTitle(), this, SLOT(showWidget()))->setData(m->windowTitle());
И пропала ошибка:
QVariant::QVariant(void*)' is private
within this context
Остались две ошибки:

invalid static_cast from type '<unresolved overloaded function type>' to type 'QAction*'
nvalid static_cast from type 'int' to type 'QWidget*


Название: Re: Список окон
Отправлено: DS_tm от Январь 22, 2010, 11:31
Мой косяк). sender - это функция, которая возвращает указатель на объект (наследник QObject), инициализирующий сообщение, а я просто скобки забыл поставить. Если вы определяете слот с параметром QAction *, то вам эта строчка не нужна, используйте передаваемую переменую.
Вместо static_const<QWidget*>(action->data().toInt()) попробуйте (QWidget*)action->data().toInt(), но если кто спросит, я вам этого не советывал))


Название: Re: Список окон
Отправлено: kadr от Январь 22, 2010, 12:18
Вот:
Код:
void nozologia::menu()
{
    int i = 0;
    QMenu *contextMenu = new QMenu;
    contextMenu->addAction("Ввод рецепта");
    contextMenu->addAction("РР-1 Отчет");
    contextMenu->addAction("РЛ-1 Отчет");
    contextMenu->addSeparator();
    contextMenu->addAction("Выход");
    contextMenu->addSeparator();  
    contextMenu->setGeometry(QCursor::pos().x(),QCursor::pos().y(),contextMenu->sizeHint().width(),contextMenu->sizeHint().height());
    contextMenu->show();
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(exit(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(vvod(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(pp1(QAction*)));
    connect(contextMenu,SIGNAL(triggered(QAction*)),this,SLOT(pl1(QAction*)));

    foreach (QWidget *m, QApplication::topLevelWidgets())
    {
        if (m->windowTitle() != "" && m->windowTitle() != "7 Нозологий" && m->isVisible())
        {
            contextMenu->addAction(m->windowTitle(), this,SLOT(showWidget()))->setData(m->windowTitle());
        }      
    }
    contextMenu->exec();

}

void nozologia::showWidget()
{
    QAction *action =  (QAction*)sender();

    if (action)
        {
             QWidget *m = (QWidget*)action->data().toInt();
             if (m) m->show();
        }
}
не хочет работать.
Все компилиться без проблем, но окна не переносятся на передний план!


Название: Re: Список окон
Отправлено: DS_tm от Январь 22, 2010, 12:44
Попробуйте еще добавить вызов activateWindow() для виджета m. То есть:

Код
C++ (Qt)
   if (m) {
     m->show();
     m->activeWindow();
   }
 

Если не сработает, проверте, верно ли определяеться виджет m, к примеру вызовете m->hide(). Если определяеться правельно, но не появляеться, то читайте ссылку что дал Вам BRE!


Название: Re: Список окон
Отправлено: SABROG от Январь 22, 2010, 12:47
еще можно попробовать void QWidget::raise ()   [slot]

только в документации нигде не сказано работает он с top level окнами или нет.


Название: Re: Список окон
Отправлено: kadr от Январь 22, 2010, 14:28
По той ссылке я не вынес ничего полезного. Все попробовал не работает.
Вот что я сделал:
qDebug() << action->text();
    qDebug() << action->objectName();
    qDebug() << action;
qDebug() << m;


Код:
void nozologia::showWidget()
{
    QAction *action =  (QAction*)sender();

    qDebug() << action->text();
    qDebug() << action->objectName();
    qDebug() << action;
    if (action)
        {
             QWidget *m = (QWidget*)action->data().toInt();

             qDebug() << m;
             if (m)
             {
                 m->setWindowFlags(m->windowFlags() | Qt::WindowStaysOnTopHint);
                 m->raise();
                 m->show();
                 m->activateWindow();

             }
        }
}
Вывод:
Код:
"Отчет РЛ-1" 
""
QAction(0x1072c2c8)
QObject(0x0)
Передается только Заголовок окна! windowsTitle();


Название: Re: Список окон
Отправлено: SABROG от Январь 22, 2010, 15:29
Так у тебя возвращается пустой указатель тут:

Код
C++ (Qt)
           QWidget *m = (QWidget*)action->data().toInt();
           qDebug() << m;
 


Название: Re: Список окон
Отправлено: BRE от Январь 22, 2010, 16:06
... и все это из-за того, что в data запихиваем WindowTitle, а получить хотим указатель на виджет.


Название: Re: Список окон
Отправлено: DS_tm от Январь 22, 2010, 16:21
В функции menu() поменяйте строчку:

Код
C++ (Qt)
contextMenu->addAction(m->windowTitle(), this,SLOT(showWidget()))->setData(m->windowTitle());
 

на:
Код
C++ (Qt)
contextMenu->addAction(m->windowTitle(), this,SLOT(showWidget()))->setData((int)m);
 

А то вы не указатель на QWidget в дате держите, а его заголовок.


Название: Re: Список окон
Отправлено: kadr от Январь 25, 2010, 16:06
... и все это из-за того, что в data запихиваем WindowTitle, а получить хотим указатель на виджет.
И что делать, как туда указатель то запихнуть?


Название: Re: Список окон
Отправлено: DS_tm от Январь 25, 2010, 19:31
Читайте мой предидущий пост.


Название: Re: Список окон
Отправлено: kadr от Январь 27, 2010, 12:40
Читайте мой предидущий пост.
Попробовал, результат не изменился, попрежнему ничего не происходит!


Название: Re: Список окон
Отправлено: svalkadoma от Ноябрь 18, 2011, 11:23
Короче решение банально простое. Когда Окно перекрывается другими (оно не на переднем плане) вызываем для него последовательно hide() и show() и ОПля окно на переднем плане :) у меня работает

Код:
if( ! isActiveWindow())
        {
            hide();
            show();
        }