Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Работа с QTabWidget
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt GUI
RazrFalcon
Как я понял работу:
создаем на форму QTabWidget;
затем создаем классы, наследники QWidget;
в этих классам создаем нужные нам элементы GUI;
в класс нашего главного окна добавляем что то в духе:
tabWidget = new QTabWidget;
tabWidget->addTab(new newTab(), tr("Tab"));
.
В итоге получаем по классу для каждого таба. Как я понял.

Проблема в том, что я не пойму, как теперь обратится к главному окну из класса-таба.
К примеру мне нужно изменить ячейку в таблице (2-й таб), а ввожу я в первом табе.
Ну или банально изменить размер окна из таба. Ведь setGeometgy вызваный из первого таба не повлияет на главное окно.

PS: табы только для примера, текущего, проблема больше в взаимосвязями с классами.


Пример:
есть 2-а класса. Главный: WallWindow, и класс таба: ListTab.
Что бы что то изменить в табе ListTab из WallWindow, я делаю следующие:
void WallWindow::something()
{
    //...
    ListTab my;
    my.startButton->setText("Start");
    //...
}
Это правильно?
Алексей1153
1) можно произвести свой класс от вкладки и там сохранять указатель на родителя нужного класса
tabWidget->addTab(new newTab(tabWidget), tr("Tab"));Language: cpp

2) сигналы и слоты
RazrFalcon
1) не понял
2) как тогда изменить иконку главного окна кнопкой находящейся в табе?
Алексей1153
1) произвести класс-вкладку от QWidget, в конструкторе принять указатель на QTabWidget-родитель. Когда нужно, просто вызываешь нужный метод по указателю

2) а как это обычно делается ? Также, только в слоте, а слот соединён с сигналом кнопки
RazrFalcon
А можно с примером кода. Так как я все равно не понял.
Алексей1153
нет, пример сейчас я писать не в состоянии. А первый пункт - это классика C++ , в любом учебнике но нему есть
RazrFalcon
Спрошу еще раз, у всех.
Как вызвать функцию, которая определена в другом классе?

Пример:
.h
Раскрывающийся текст
class ListTab : public QWidget
{
    Q_OBJECT

public:
    ListTab(QWidget *parent = 0);

public slots:
    QFileInfoList load_and_show();
};

class settingTab : public QWidget
{
    Q_OBJECT

public:
    settingTab(QWidget *parent = 0);
private slots:
    void on_addFolderButton_clicked();
};


Мне нужно вызвать load_and_show(); в void settingTab::on_addFolderButton_clicked(){}. Как?
wiz29
Цитата(RazrFalcon @ 11.4.2011, 14:22) *
Мне нужно вызвать load_and_show(); в void settingTab::on_addFolderButton_clicked(){}. Как?

Для этого нужно иметь экземпляр класса ListTab в settingTab и вызвать соответствующий метод экземпляра класса (ListTab::on_addFolderButton_clicked).

но на самом деле вопрос поставлен не вполне корректно.
RazrFalcon
А пример можно? Я ничего не понял.
wiz29
тут нужно четко понимать что ты хочешь сделать. и не путать класс с экземпляром класса... Если QFileInfoList load_and_show() имеет статическую природу, тогда объяви эту функцию как статическую, если же данная функция имеет не статическую природу , тогда, в любом случае, придется иметь экземпляр одного класса в описании другого и с этим ничего не поделать.

Цитата(RazrFalcon @ 11.4.2011, 14:39) *
А пример можно? Я ничего не понял.

Для того куска кода который приведен выше , это будет выглядеть так:
class ListTab : public QWidget
{
    Q_OBJECT

public:
    ListTab(QWidget *parent = 0);

public slots:
    QFileInfoList load_and_show();
};

class settingTab : public QWidget
{
    Q_OBJECT

public:
    settingTab(QWidget *parent = 0);
private slots:
    void on_addFolderButton_clicked()
    {
         if (m_pListTab)
         {
              m_pListTab->load_and_show();
         }
    }
private:

    ListTab* m_pListTab;
};

Детали инициализации я здесь пропущу.
RazrFalcon
Блин!
Оно и до этого работало. Программа падала именно в load_and_show(), а не при определении класса.
Осталось понять в чем проблема.
wiz29
вообще что то несвязное, код в студию. (весь)
RazrFalcon
Вот в чем проблема:
settingTab::settingTab(QWidget *parent) : QWidget(parent)
{
  settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                           "wallpapers-changer", "wallchanger");

  addFolderButton = new QPushButton("Add folder",this);
  connect(addFolderButton, SIGNAL(clicked()), this, SLOT(on_addFolderButton_clicked()));
}

void settingTab::on_addFolderButton_clicked()
{
  QString selectedDir = QFileDialog::getExistingDirectory(this,
                                                          "Open Image(s)",
                                                          "/media/data",
                                                          QFileDialog::ShowDirsOnly);
  folderListWidget->addItem(selectedDir);
  dirList.append(selectedDir);

  if (!dirList.isEmpty())
    settings->setValue("settings/dirList",dirList);

  if (!settings->value("settings/dirList").toStringList().isEmpty()) {
    m_pListTab->load_and_show();
  }
}

не создается файл конфигов, settings. А если закомментить m_pListTab->load_and_show(); - то создается. А load_and_show() как раз его и читает. И получается, что оно читает файл который не создался, и программа убивается.
wiz29
программа убивается на строке:
m_pListTab->load_and_show();
?

если это так, то покажи пожалуйста код где инициализируется объект m_pListTab.
RazrFalcon
Нет. При попытке прочесть QSettings в load_and_show();

Инициализация:
class settingTab : public QWidget
{
    Q_OBJECT

public:
    QSettings *settings;
    ...

private slots:
    void on_addFolderButton_clicked();

private:
    ListTab* m_pListTab;
};
wiz29
возможно кинуть код проекта архивом, или архивом целиком файлы с данными классами, просто отрывки не отражают всей картины.
RazrFalcon
Еще сырой.
wiz29
Проблема банальна, у тебя не инициализирована m_pListTab, т.е. адрес этого объекта = мусор. Инициализируй его в конструкторе класса settingTab

просто разыменование "мусора" ведет к непредсказуемому результату. это и вызывало падения...
RazrFalcon
Так что ли?
m_pListTab = new ListTab;
wiz29
settingTab::settingTab(QWidget *parent) : QWidget(parent)
{
  m_pListTab = new ListTab(this);
  settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                           "wallpapers-changer", "wallchanger");

  picFolders = new QLabel("Pictures folders:",this);
  addFolderButton = new QPushButton("Add folder",this);
  connect(addFolderButton, SIGNAL(clicked()), this, SLOT(on_addFolderButton_clicked()));
  folderListWidget = new QListWidget(this);
  QGridLayout *my = new QGridLayout;

  //QStringList dirList;
  //dirList = new QStringList;
  dirList = settings->value("settings/dirList").toStringList();
  //dirList<<"/media/data/Additional/Pictures"<<"/media/data/Additional/Images";

  my->addWidget(picFolders,0,0,1,3);
  my->addWidget(folderListWidget,1,0,1,3);
  my->addWidget(addFolderButton,2,0);
  setLayout(my);

  for (int i=0; i<dirList.count(); ++i) {
    folderListWidget->addItem(dirList.at(i));
  }

  if (!dirList.isEmpty())
    settings->setValue("settings/dirList",dirList);
}


Совет: по максимому используй возможности QtDesigner для создания диалогов, будет менее мусорный и читабельный код. Просто не имеет смысла "ковыряться" с размещением и компоновкой элементов, там где это реально не нужно. Это тебе сэкономит кучу времени на более полезные задачи.
RazrFalcon
Я так делал. Но таблица в первом табе не заполняется.

На счет совета: я знаю, просто ради интереса хотелось и в этом разобраться. Понять как оно изнутри работает.
wiz29
Цитата(RazrFalcon @ 11.4.2011, 16:23) *
Я так делал. Но таблица в первом табе не заполняется.

На счет совета: я знаю, просто ради интереса хотелось и в этом разобраться. Понять как оно изнутри работает.

так твоя таблица должна быть связана с settingsTab?


если это так, тогда все просто

измени конструктор settingTab на settingTab(ListTab* pListTab, QWidget *parent = 0)
settingTab::settingTab(ListTab* pListTab, QWidget *parent) : QWidget(parent)
{
    m_pListTab = pListTab;
  settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
                           "wallpapers-changer", "wallchanger");
...............
}

WallWindow::WallWindow()
{
........

  listTab = new ListTab;
  settTab = new settingTab(listTab);
........
}



RazrFalcon
Ура! Спасибо. Работает как надо.
Я бы сам не додумался до такого. Просто еще не разу с таким количеством классов не сталкивался.
Теперь по аналогии можно доделывать все что я хотел.
RazrFalcon
И снова эти табы!
Теперь проблема с Ui
.h
Раскрывающийся текст
#ifndef WALLWINDOW_H
#define WALLWINDOW_H

#include <QMainWindow>
#include "ui_wallwindow.h"

class WallWindow : public QMainWindow, private Ui::WallWindow
{
    Q_OBJECT

public:
    WallWindow(QWidget *parent = 0);
};

class ListTab : public QWidget, private Ui::WallWindow
{
    Q_OBJECT

public:
    ListTab(QWidget *parent = 0);

public slots:
};

class folderTab : public QWidget, private Ui::WallWindow
{
    Q_OBJECT

public:
    folderTab(QWidget *parent = 0);

public slots:
};

#endif // WALLWINDOW_H

.cpp
Раскрывающийся текст
#include <QtDebug>

#include "wallwindow.h"

WallWindow::WallWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setupUi(this);
    //QWidget *mainWidget = new QWidget;
    //mainWidget->setLayout(verticalLayout);
    //setCentralWidget(mainWidget);
    qDebug()<<gridLayout_2->rowCount();
    gridLayout_2->setAlignment(spinBox,Qt::AlignRight);
}

ListTab::ListTab(QWidget *parent) : QWidget(parent)
{
    //gridLayout_2->setAlignment(spinBox,Qt::AlignRight);
    //setLayout(gridLayout_2);
    //qDebug()<<gridLayout_2->rowCount();
    //gridLayout_2->itemAtPosition(0,5)->setAlignment(Qt::AlignRight);
}


Все что я делаю в ListTab::ListTab не на что не влияет. Даже qDebug() не обрабатывается!
wiz29
естественно не работает, потому что не правильно делаешь:) Выложи код если не трудно, посмотрю
RazrFalcon
Да знаю что не правильно. Тут то табы уже созданы. А если делать как я раньше делал, то нужно было их создавать.
wiz29
Сделай проще архитектурно, у тебя есть один диалог с табом, причем табы не динамические.
Тут у тебя есть уже готовые объекты которыми будешь управлять из WallWindow.
ListTab и FolderTab у тебя вообще не используется, тк вся форма создается в дизайнере вместе с наполнением. У тебя есть доступ ко всем объектам табов по именам в любой части WallWindow, поэтому не стесняясь можно создавать нужные слоты в WallWindow и наполнять функциональностью.
P.S. не забывай нормально именовать объекты в QtDesigner, самому будет проще разбираться что к чему, тк имена переменных pushButton1, pushButton2 не информативны:)

class WallWindow : public QMainWindow, private Ui::WallWindow
{
    Q_OBJECT

public:
    WallWindow(QWidget *parent = 0);

private slots:

    void on_addFolderButton_clicked();
    void tableFill();
    int setImage();
    void processStart(QString path, QString arg);
    QList<int> createRandomNumberList();

    void startButton_clicked();
    void on_onlynames_checkBox_stateChanged(int );
    void on_timeBox_valueChanged(int );
    void addButton_clicked();
    void on_table_cellDoubleClicked(int row, int column);
    void on_table_cellClicked(int row, int column);
    void clearButton_clicked();
    void on_pos_comboBox_currentIndexChanged(QString name);
    void order_comboBox_currentIndexChanged(QString name);
    void config_save();
    void nextImage();
    void previousImage();
    void iconActivated(QSystemTrayIcon::ActivationReason reason);
};


Остальные классы тебе в данном случае не нужны
RazrFalcon
Да-да. Это просто тестовый проект.

То есть, как я понял, допклассы создавать не нужно. Можно все реализовывать через WallWindow?
wiz29
Цитата(RazrFalcon @ 12.4.2011, 14:31) *
То есть, как я понял, допклассы создавать не нужно. Можно все реализовывать через WallWindow?

Именно так и есть. Тебе доступны все объекты форм в WallWindow. не зависимо от того в каком из табов они расположены.
RazrFalcon
Тогда получается, что работать с дизайнером действительно проще ^_^
wiz29
Дизайнер избавляет от "груды" однотипного и рутинного кода, экономя на этом время.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.