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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Qmenu - Получение списка выделенных пунктов  (Прочитано 8684 раз)
NIKE-SPAWN
Гость
« : Январь 28, 2006, 15:27 »

Возникла такая проблема...
Код:

1
2
3---5   (8)
4    6    9
      7---10

Есть меню.. надо узнать узнать путь кот. сделал пользователь.. т.е. для примера это 378...
Проблема в том что меню генериться динамически..
Пробовал отслеживать через hovered() и составть путь "в ручную"... не выходит..т.к. после 3 не узнать куда пошол на 2 или 5.. Да  и всегда мона перескочть с 8 на 1...
Всё было б просто если б для каждого эл-та точно знать его место..
ps
qt4.1
Записан
Steven_Orko
Гость
« Ответ #1 : Январь 28, 2006, 17:23 »

А почему бы тебе не строить дерево идентификаторов пунктов меню (например, дерево из QAction, не обязательно бинарное)?  Алгоритмов построения дерева в инете много. Когда генеришь меню, то сначала генеришь дерево объектов QAction.  На основе QAction  строишь свое меню. Ну, а QAction уже привязываешь к нужным тебе слотам.

Все алгоритмы по работе с деревом уже известны, надо только в инете поискать. Могу посоветовать тебе www.rsdn.ru. ИМХО, другого более оптимального способа решение проблеммы не вижу...
Записан
NIKE-SPAWN
Гость
« Ответ #2 : Январь 28, 2006, 18:04 »

Каждое подменю генериться тока при наведении на него.. и удаляеться при потери фокуса..
Ты предлагаешь к каждому идентификатору приписать вусь путь до него??
QMap<QAction,QString>??
Записан
Steven_Orko
Гость
« Ответ #3 : Январь 28, 2006, 19:41 »

Нет. У тебя есть самое верхнее меню, которое есть всегда. Это будет корень дерева. Пишешь (скачиваешь исходник) класс дерева, не QMap, а дерево.
Корнем его делаешь самое верхний пункт меню. Когда вызывается сигнал hovered() (как я понял ты через него это делаешь), вызываешь определенный слот, который формирует само подменю.

Единственное не понятно, у тебя набор условий для генерации меню ограничен? Можно задать все варианты генерации меню?
Если нет, то можно сделать следующее.

Создаешь объект-идентификатор:
Код:

class CMenuItemID : public QObject
{
Q_OBJECT
public:
CMenuItemID(CMenuItemID* parent, QAction *action) : m_pParent(parent), m_pAction(action)
{
connect(action, SIGNAL(hovered()), this, SLOT(onHovered()));
};

virtual ~CMenuItemID() {};

public slots:
void onHovered()  //  <<------- Процедура генерации нового  подменю
{
//Твой код
};

private:
CMenuItemID *m_pParent;
QAction     *m_pAction;
};


Этот объект будет также элементом дерева. Как видишь, у него есть указатель на его родителя, а у родителя есть указатель на его родителя, и так до самого корня. Просмотреть можно. Алгоритмы стандартные. Класс дерева писать не буду, поищи в инете. Помниться где-то видил его как шаблон, но не помню где.

Таким образом, алгоритм следующий:
1. Создаешь класс - элемент дерева. Он описан выше.
2. Создаешь класс дерева, в котором элементами будет указанный в первом пункте класс.
3. Создаешь корень дерева. Все.

Далее каждое отдельное подменю будет генериться на основе написанного тобой алгоритма в слоте void onHovered() класса элемента дерева. Здесь ты должен предусмотреть все возможные варианты.

Да, в классе дерева, в конструкторе можешь передават также указатель на меню, чтобы твой объект "дерево" сам добавлял в него новые пункты меню, когда у него появляется новый элемент.
Записан
NIKE-SPAWN
Гость
« Ответ #4 : Январь 28, 2006, 20:16 »

Цитировать

Единственное не понятно, у тебя набор условий для генерации меню ограничен? Можно задать все варианты генерации меню?

А что ты под этим понимаешь?? Какие варианты?
А класс дерева уже ищу.. вместе с алгоритмом..
и как мне тогда мона будет узнать на каком уровне я щас нахожусь?
ну для ситуаций когда перескочит с 4 на 1.. наример?
Записан
Steven_Orko
Гость
« Ответ #5 : Январь 28, 2006, 20:49 »

Цитата: "NIKE-SPAWN"
Цитировать

Единственное не понятно, у тебя набор условий для генерации меню ограничен? Можно задать все варианты генерации меню?

А что ты под этим понимаешь?? Какие варианты?

Уже неважно. Я привел более универсальный механизм.

Цитировать

А класс дерева уже ищу.. вместе с алгоритмом..
и как мне тогда мона будет узнать на каком уровне я щас нахожусь?


Когда наводишь мышку, срабатывает слот соответствующего узла дерева. При этом в этом объекте также содержится указатель на выделенный мышкой пункт меню (и делай с ним, что хочешь  :wink: ) Как ему(узду дерева) узнать, на каком уровне он находится? См. инфу по деревьям.  Подсказка: подсчитать, сколько предков у него есть, передя по всей цепочке предков, а заодно можно сформировать весь полный путь к выделенному пункты меню.
Цитировать

ну для ситуаций когда перескочит с 4 на 1.. наример?

Не понял вопроса. Что значит - "перескочит"?


Да, некоторая поправочка в коде:
Код:
class CMenuItemID : public QObject 
{
Q_OBJECT
public:
CMenuItemID(CMenuItemID* parent, QAction *action) : m_pParent(parent), m_pAction(action)
{
connect(action, SIGNAL(hovered()), this, SLOT(onHovered()));
};

virtual ~CMenuItemID()
{
delChildNodes(); //Удаляем все свои дочерние узлы
//Здесь, если хочешь, можешь удивать также объект QAction
//Хотя, наверно, так и придется делать.
};

CMenuItemID* addNode(CMenuItemID* node)
{
//Здесь твой код
return node;
}

void delChildNodes()
{
if (m_pNodes.count() > 0)
{
QVector<CMenuItemID*>::iterator first = m_pNodes.begin();
QVector<CMenuItemID*>::iterator last  = m_pNodes.end();

for(; first != last; ++first)
{
//Удаляем узел, он в свою очередь в деструкторе удалит
//все свои дочерние узлы
delete (CMenuItemID*) *first;
}
m_pNodes.clear();      // C помощью этих трех строчек
QVector buf;           // освобождаем память, занимаемую
swap(buf, m_pNodes);   // вектором указателей на дочерние узлы
}
}

public slots:
void onHovered()  //  <<------- Процедура генерации нового  подменю
{
//Твой код
};

private:
CMenuItemID *m_pParent;
QAction     *m_pAction;
QVector<CMenuItemID*> m_pNodes; //  <<- вектор дочерних узлов
};


Весь код писать не буду, додумай сам.
Скажу только, что если ты генеришь меню сам каждый раз при выборе пункта меню, то надо проверять, а не было ли оно сгенерено уже когда-то? И тут сам думай, что делать: либо показывать старое меню, либо удалять его, а потом уже  тогда создавать новое. Да, и позаботься об удалении QAction в деструкторе CMenuItemID. Я этого туда не писал. ))) Если что, спрашивай, уточняй )))) Удачи!!!
Записан
NIKE-SPAWN
Гость
« Ответ #6 : Январь 30, 2006, 01:25 »

мда.. всё почти получилось..
с деревьями не вышло.. ничеого не нашёл по ним.. пришлось с QMap биться.. добился..!
тока теперь возникли новые проблемы..:
как мона ускорить отображение меню??? Поставил задержку перед появление в 0 всё равно долго грузит..
почит статеек понял что это из-за connect() их слишком много..

храниться меню в Qmap<QString,QMenu> потом добаляются куда QAction'ов и всё это дело конектиться..
connect(Menг,SIGNAL(hovered( QAction *)),this,SLOT(hoverElement( QAction *)));
        connect(Menu,SIGNAL(triggered( QAction *)),this,SLOT(clickedElement( QAction *)));
как это дело мона всё упростить?..
Записан
Steven_Orko
Гость
« Ответ #7 : Январь 30, 2006, 04:24 »

Цитировать

мда.. всё почти получилось..
с деревьями не вышло.. ничеого не нашёл по ним.. пришлось с QMap биться.. добился..!


    www.rsdn.ru -> Статьи -> Алгоритмы  - Куча статей по деревьям.
    www.rsdn.ru -> Поиск по слову "Деревья" - результатов много.[/list]

    Цитировать
    как это дело мона всё упростить?..

    См. выше...
    Записан
    Вудруф
    Гость
    « Ответ #8 : Январь 31, 2006, 10:14 »

    map - тоже подходит для исполнения дерева
    предок, вектор потомков
    std::map <unsigned long int, std::vector <unsigned long int> >
    где unsigned long int - идентификатор предка или потомка, можно вставить указатель на объект

    Только вот я не понимаю, почему все используют QMap вместо std::map...

    А насчёт ускорения - можно в фоне генерировать меню "на шаг вперёд". Либо отдельным тредом, либо с периодической вставкой вызовов обработки событий.
    Записан
    NIKE-SPAWN
    Гость
    « Ответ #9 : Февраль 01, 2006, 09:43 »

    мона ли в qt сделать что бы большие меню не вылезали в несколько  столбцов, а как в винде появлялиь стрелочки вверх/вниз..
    или их  надо самому делать??

    А кроме бинарных какие ещё деревья есть?? а то мне как я понял они не подоёдут..
    Записан
    Steven_Orko
    Гость
    « Ответ #10 : Февраль 01, 2006, 15:26 »

    Бинарные деревья - это грубо говоря, такие деревья,  в которых у каждого родительского узла может быть не более двух дочерних узлов.
    Есть несколько разновидностей бинарных деревьев. Все они построены по определенному принципу, который может приследовать либо увеличение скорости сортировки, либо поиска и т.д.
    Тебе надо обычное дерево, в котором каждый узел может иметь сколько угодно дочерних узлов. Впринципе, прототип такого узла я тебе написал. Каждый узел должен хранить в себе указатели на все свои дочерние узлы. Это можно делать либо напрямую в массиве, но это фигово. Можно в std::vector или std::map, или их аналоги QVector или QMap. Последнее следует использовать, если твоя Qt собрана без поддержки STL.
    Насчет ускорения Вудруф прав. Тебе надо в отдельном потоке создавать поддерево, ну, т.е. новое меню для каждых пунктов меню, которое пользователь уже видит, но не успел выбрать. Эдак на шаг опережать события.
    Записан
    Страниц: [1]   Вверх
      Печать  
     
    Перейти в:  


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