Идеология Qt. Как сделать конкретное приложение?
не только схему, но и саму рабочую программу.сильно
Чтение туториалов и примеров не спасло отца русской демократии?
не спасло, в примерах есть только реализация самих табов, а инфа между ними не передаётся
кстати, есть какой-нибудь "дизайнер форм", типа как в дельфях? интересует для кутэ и гтк
Есть, ставится вместе с Qt, называется Designer, но он не такой как в дельфи, там только расставляешь кнопки по формам, писать код надо отдельно.
каждый экземпляр таба это свой отдельный класс,дельфинизмы в реальной жизни =)
каждый таб это экземпляр отдельного класса - так точнее?
Для Qt есть Qt designer, есть более-менее удобный плагин для Эклипса.
Есть вариант сделать свой класс, который будет своего рода "транспортным агентом" для сигнала между двумя табами. То есть связь типа сигнал первого таба -> слот этого класса -> сигнал этого класса -> слот другого таба.
глюк оговорился, тем более что в дельфях это не так.
На окне две вкладки QTabWidget. На одной из них находятся некоторые контролы, например текстовое поле и кнопка. На другой находится другое текстовое поле. Я хочу "передать" информацию с первой вкладки на вторую по нажатию кнопки. Просто чтобы она туда скопировалась. Как идеологически правильно это делать?Как раз для таких случаев и придумана концепция Model-View-Controller. Идея такова: у нас есть объект, который хранит данные (например, textData:String). Каждый таб, когда в нем меняется текст, изменяет поле textData, а при каждом изменении textData (или, как вариант, при каждом переключении или отрисовке таба значение текстового поля в табе берется из textData.
Таким образом ты абстрагируешься от способа отображения информации и даешь себе возможность поддерживать свои табы в консистентном состоянии
пытался описать поведение этого паттерна.
Я бы ему еще дал (в контексте данной задачи) названия Synchronizer, Notifier.
src/main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <QtGui>
#include <QObject>
#include <QApplication>
#include "mainwnd.h"
int main ( int argc, char ** argv )
{
QApplication app ( argc,argv );
QTextCodec::setCodecForCStrings ( QTextCodec::codecForName ( "UTF8" ) );
MyWidget * widget;
widget = new MyWidget;
widget->show ;
printf("(1)\n");
//QObject::connect ( widget->lineEdit_2,SIGNAL ( returnPressed widget,SLOT ( OnChange ) );
printf("(2)\n");
return app.exec ;
}
src/mainwnd.cpp
//fdaf
#include "mainwnd.h"
#include <stdio.h>
MyWidget::MyWidget {
int i;
ui.setupUi(this);
//QObject::connect ( lineEdit_2,SIGNAL ( returnPressed this,SLOT ( OnChange ) );
QPushButton * pButton = findChild<QPushButton*>("pushButton");
if(pButton) {
connect (pButton, SIGNAL(clicked this, SLOT(clicked_slot;
}
return;
}
MyWidget::~MyWidget {
return;
}
void MyWidget::clicked_slot {
QLineEdit * pEditfrom = findChild<QLineEdit*>("lineEdit_from");
QLineEdit * pEditto = findChild<QLineEdit*>("lineEdit_to");
if(!pEditfrom || !pEditto)
return;
pEditto->setText(pEditfrom->text;
return;
//printf("test\n");
}
src/mainwnd.h
//fdaf
#ifndef MAINWND_H
#define MAINWND_H
#include <QtGui/QMainWindow>
#include "ui_mainwnd.h"
class MyWidget : public QMainWindow, public Ui::MainWindow {
Q_OBJECT
public:
MyWidget;
~MyWidget;
private:
Ui::MainWindow ui;
public slots:
void clicked_slot;
};
#endif // MAINWND_H
src/mainwnd.ui
<ui version="4.0" >
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>733</width>
<height>553</height>
</rect>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget" >
<widget class="QTabWidget" name="tabWidget" >
<property name="geometry" >
<rect>
<x>0</x>
<y>10</y>
<width>721</width>
<height>491</height>
</rect>
</property>
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
<string>Tab 1</string>
</attribute>
<widget class="QLineEdit" name="lineEdit_from" >
<property name="geometry" >
<rect>
<x>80</x>
<y>100</y>
<width>113</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton" >
<property name="geometry" >
<rect>
<x>400</x>
<y>210</y>
<width>75</width>
<height>24</height>
</rect>
</property>
<property name="text" >
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_2" >
<attribute name="title" >
<string>Tab 2</string>
</attribute>
<widget class="QLineEdit" name="lineEdit_to" >
<property name="geometry" >
<rect>
<x>90</x>
<y>100</y>
<width>113</width>
<height>20</height>
</rect>
</property>
</widget>
</widget>
</widget>
</widget>
<widget class="QMenuBar" name="menubar" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>733</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar" />
</widget>
<resources/>
<connections/>
</ui>
CMakeLists.txt
PROJECT(tab2)
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Debug) #build with debug support
ENDIF (NOT CMAKE_BUILD_TYPE)
SET(QT_USE_QTMAIN True)
FIND_PACKAGE(Qt4 REQUIRED) # find and setup Qt4 for this project
INCLUDE(${QT_USE_FILE})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(main_SRCS
src/main.cpp
src/mainwnd.cpp
)
SET(main_HDRS
src/mainwnd.h
)
SET(main_UIS
src/mainwnd.ui
)
SET(main_MOC_HDRS
src/mainwnd.h
)
SET(tab2_SRCS
${main_SRCS}
)
SET(tab2_MOC_HDRS
${main_MOC_HDRS}
)
SET(tab2_HDRS
${main_HDRS}
)
SET(tab2_UIS
${main_UIS}
)
MESSAGE(STATUS "!")
MESSAGE(STATUS "SRC: ${tab2_SRCS}")
MESSAGE(STATUS "MOC_HDRS: ${tab2_MOC_HDRS}")
MESSAGE(STATUS "HDRS: ${tab2_HDRS}")
MESSAGE(STATUS "UIS: ${tab2_UIS}")
#SET(aa1_RES
#)
#QT4_ADD_RESOURCES(aa1_RES_GEN ${a1a1_RES})
QT4_WRAP_UI(tab2_UIS_H ${tab2_UIS})
QT4_WRAP_CPP(tab2_MOC_SRCS ${tab2_MOC_HDRS})
MESSAGE(STATUS "SRC: ${tab2_SRCS}")
MESSAGE(STATUS "MOC_HDRS: ${tab2_MOC_HDRS}")
MESSAGE(STATUS "HDRS: ${tab2_HDRS}")
MESSAGE(STATUS "UIS: ${tab2_UIS}")
MESSAGE(STATUS "UIS_H: ${tab2_UIS_H}")
MESSAGE(STATUS "MOC_SRCS: ${tab2_MOC_SRCS}")
IF (WIN32)
ADD_EXECUTABLE(tab2 WIN32
${tab2_UIS_H}
${tab2_MOC_SRCS}
${tab2_SRCS}
${tab2_HDRS}
)
TARGET_LINK_LIBRARIES(tab2 ${QT_LIBRARIES} ${tab2_LIBS})
ELSE (WIN32)
ADD_EXECUTABLE(tab2
${tab2_UIS_H}
${tab2_MOC_SRCS}
${tab2_SRCS}
${tab2_HDRS}
)
TARGET_LINK_LIBRARIES(tab2 ${QT_LIBRARIES} ${tab2_LIBS})
ENDIF (WIN32)
собcтвенно, всё
для компиляции:
# mkdir build
#cd build
#cmake ..
#make
#./tab2
ps: если есть способ сделать тоже самое проще, то с удовольствием выслушаю, потому как не всё в выше изложенном мне видится правильным
CMakeLists.txtреспектище только за это уже
#cd build
#cmake ..
а вот это беру на вооружение.
значит сигналы должны идти между объектами разных классовМожешь объяснить для тех, кто сейчас в танке, но когда-то был знаком с QT, в чем проблема передавать сигнал между экземплярами разных классов?
круто, оно работает... щас буду разбираться, задам еще несколько вопросов по конкретной реализации
Можешь объяснить для тех, кто сейчас в танке, но когда-то был знаком с QT, в чем проблема передавать сигнал между экземплярами разных классов?В мануале и примерах такой ситуации не нашел... ну тупой я.
Так все-таки, проблема передавать сигнал между разными классами есть или нет?
QPushButton * pButton = findChild<QPushButton*>("pushButton");
if(pButton) {
connect (pButton, SIGNAL(clicked this, SLOT(clicked_slot;
}
здесь pButton добывается из недр класса Ui_MainWindow, от которого наследуется MainWindow, а clicked_slot - член класса MyWidget, который потомок Ui::MainWindow
проблемы, видимо, нет, но сама процедура замороченная, извините за резкость
собственно ui_mainwnd.h - содержит функцию setupUi
можно было всё, что там написано руками написать, но мне проще в designer нарисовать и при этом не заморачиваться с uic mainwnd.ui > ui_mainwnd.h
например, я передвинул кнопочку, пишем make, кнопочка в бинарнике передвинулась.
когда-то давно(когда я ещё не прогал, но кто-то прогал на qt) после каждой перерисовки формочки приходилось запускать uic, либо дописывать в конструктор класса.
в uic4 разделили визуальные объекты, создаваемые designer и то, что пишет человек. т.е. сейчас ui_*.h файлы не содержат пользовательского кода, а генерятся из .ui файлов.
в результате, согдаётся потомок Ui::MainWindow, который уже содержит пользовательские данные, и вызывается функция setupUi, которая создаёт все элементы и коннектит всё что сконнекченно визуально на формочке
QPushButton * pButton = findChild<QPushButton*>("pushButton"); - это я так нашёл кнопочку.
если кто знает, как это сделать проще - пожалуйста, скажите.
я не нашёл.
clicked_slot - это та функция которая должна быть вызвана, когда нажимается кнопочка.
мне намного больше нравится дельфи(бюлдер)-способоб кликнул на кнопочку попал в то место, где писать код, но..
QPushButton * pButton = findChild<QPushButton*>("pushButton");
if(pButton) {
connect (pButton, SIGNAL(clicked this, SLOT(clicked_slot;
}
здесь pButton добывается из недр класса Ui_MainWindow, от которого наследуется MainWindow, а clicked_slot - член класса MyWidget, который потомок Ui::MainWindow
проблемы, видимо, нет, но сама процедура замороченная, извините за резкость
за функцию findChild огромное спасибо, не подозревал о ее существовании, я только начинаю изучение Qt
ак сделать конкретное приложение?
Для этого нужно поставить чисто конкретную IDE на реальный комп, взять дерзкую мышь и клаву и в путь
под нормальной понимается ,например msvs c виз. редактором, дебагером и прочими радостями.
то, что я запостил выше можно экспортировать в проект и дальше прогать там:
кстати, по поводу cmake
#mkdir build-kdev
#cd build-kdev
#cmake -GKDevelop3 ..
для msvs тоже можно, но я парамент для -G не помню(можно посмотреть cmake -h)
мне намного больше нравится дельфи(бюлдер)-способоб кликнул на кнопочку попал в то местоЕсть как за, так и против идеологии визуального проектирования. Я тоже по началу юзал QTDesigner, но потом сам факт, что какая-то прога прогает за меня, стал настораживать. И действительно, код, написанный руками и читается лучше, и занимает, как правило, меньше строк, причем, раза в полтора.
под нормальной понимается ,например msvs c виз. редактором, дебагером и прочими радостямиКстати, под линуксами альтернатива всему этому тулкиту - набор стандартных прог типа gdb, make плюс симпатичный текстовый редактор, распознающий скобки и способный подсвечивать синтаксис (а также "обучаться" ему посредством языковых файликов). Например, редакторы Kate и Anjuta вполне пригодны для кодинга в разумных масштабах. В силу кроссплатформенности QT можно вести разработку, сидя под линуксами.
задача:
нужен визуальный редактор регистров одной железки.
решение:
создаётся виджет smartylineedit - это обычный lineedit, но с добавлением некотрых сигналов и слотов.
создаётся виджет controlbox, который взаимодействует с библиотекой.
теперь самое интересное, создаётся плагин к designer, и новые едиты со свойством адреса регистра можно добавлять прям на формочку.
добаление новых полей регистров сводится к перетаскиванию виджета с панельки на форму и вбиванием одного числа.
все коннекты сделаны в классе формочки.
визуальные редакторы - это не самоцель, это лишь средство экономии времени.
самое забавное, что я нормально не разобрался, как оно всё работает, пока руками всё не сделал.
но мне как-то больше нравится способ визуальной отладки.
нажал "паузу" и посмотрел, что лежит в переменных. когда переменная лежит в классе, а он ещё в одном клссе, а тот ещё чёрт знает где, задолбаешь это всё в gdb писать
задолбаешь это всё в gdb писатьэт-точно. Правда, не всегда есть возможность отлаживаться в визуальной среде. Приходится подчас собираться на каком-нибудь серваке и запускать прогу на больших данных. Тащить файл в десятки гигов себе на десктоп нет возможности, да и сервак 64-разрядный. Приходится юзать putty + gcc + gdb
файл в десятки гигов себе на десктоп нет возможности, да и сервак 64-разрядный.имхо, VS может аттачится к удаленной машине (подробности не знаю, как там 64-разрядами тоже не в курсе)
Приходится юзать putty + gcc + gdbНа десктоп ставь Линукс
имхо, VS может аттачится к удаленной машине (подробности не знаю, как там 64-разрядами тоже не в курсе)Лол, на удалённой машине, особенно если она 64 битная, почти наверное не венда стоит
На десктоп ставь Линуксплюсадин, у нас на работе все так и делают: либо линукс, либо макось. Венда в явном меньшинстве.
И что же на линуксе предлагается вместо "putty + gcc + gdb" ?
Лол, на удалённой машине, особенно если она 64 битная, почти наверное не венда стоиту нас винда
sshfs, gnomevfs и пр. радости жизни. Правда, без gdb никак, всё равно нужно аттачиться к запущенному процессу именно удалёно. И компилить тоже нужно удалённо.
у нас на работе все так и делаюто, ты устроился таки на работу. Прогресс
На десктоп ставь ЛинуксСобственно, в процессе принятия решения. Изначально просто винда стояла, а тратить день-другой на переезд все никак не хотелось.
Как раз для таких случаев и придумана концепция Model-View-Controller. Идея такова: у нас есть объект, который хранит данные (например, textData:String). Каждый таб, когда в нем меняется текст, изменяет поле textData, а при каждом изменении textData (или, как вариант, при каждом переключении или отрисовке таба значение текстового поля в табе берется из textData.Ну, а если это начать программировать (я имею ввиду в общем случае, может в Qt это не совсем так, я с ним не работал то возникнет куча деталей, которые могут отбить всякую охоту использовать MVC.
Таким образом ты абстрагируешься от способа отображения информации и даешь себе возможность поддерживать свои табы в консистентном состоянии
Например, изменение текста контолируется нажатием кнопки, то есть соотв. методом (типа onClick (С# кажется или еще в др. яз.) или actionPerformed в Яве). Значит, это обработчик должен "видеть" объект tab'a, и эту связь нужно организвать, что в итоге (если делать все напрямик) приводит к тому, что нужно наследовать от стандартного класса "кнопка" и добавлять туда ссылку на tab. Tab в свою очередь должен иметь ссылку на текстовое поле, чтобы вытащить оттуда текст. Кроме того, каждый tab должен иметь ссылку на объект, который хранит данные и textData:String в том числе, а это опять же - наследование от стандартного виджета. Кроме того, это жесткая связь с типом данных: если этот тип поменять, то придется менять все виджеты, которые используют этот тип данных. (Кстати, возится с textData:String могла бы и кнопка...)
В общем, основная проблема в том, как делать обработчики событий и как передать инфо из них другим частям приложения, которые зависят от данного события. В любом случае обработчик должен нужно связывать с другими объектами, то есть расширять стандартную функциональность с помощью наследования. Для пары табов это еще ничего, а когда еще куча меню и прочих контролов и еще диалоги, можно запариться создавать отдельный класс для каждого виджета и еще и инициализировать и отслеживать все связи между ними.
В Яве можно выкручиваться с помощью анонимных классов в качестве обработчиков. Если все виджеты запихать в один класс, то тогда анонимные классы будут иметь к ним простой доступ как к полям класса. Но... если опять же куча виджетов, получится класс-монстр, и бегать потом по нему в поисках нужного обработчика или виджета тоже не особо приятно.
Ну, и еще конечно нужен механизм оповещения об изменениях. Пример со вторым tab'ом будет работать, поскольку tab будет автоматически перерисовываться, когда мы кликнем на нем. Но в общем случае все виджеты, которые должы знать об изменении текста, должны быть оповещены. Это делается с помощью паттерна Observer, который должен быть реализован в объекте, которыей управляет всеми данными, потому что изменения происходят там. Но с Observer'ом свои заморочки...
а когда еще куча меню и прочих контролов и еще диалоги, можно запариться создавать отдельный класс для каждого виджета и еще и инициализировать и отслеживать все связи между ними.Запариваться надо скорее над гуём, чтобы не делать лишних меню, контролов и диалогов.
Запариваться надо скорее над гуём, чтобы не делать лишних меню, контролов и диалогов.
Ну, да, и это тоже. Называется словами "правильный/хороший дизайн", "юзабилити" и все такое.
Но в итоге любой гуи-дизайн нужно все равно кодить. И если это, скажем, нехилый текстовый редактор, то там все равно будет куча меню и огромный тулбар и много разных диалогов, как ни убирай лишнее.
сам факт, что какая-то прога прогает за меня, стал настораживать.Странно! Многие люди только тем и занимаются, что пишут проги, которые за них будут писать другие проги, а тебя настораживает это...
Мне было просто не совсем очевидно, что генеримое автоматически - это в точности что надо.
Оставить комментарий
Elina74
Решил я создать такое приложение:На окне две вкладки QTabWidget. На одной из них находятся некоторые контролы, например текстовое поле и кнопка. На другой находится другое текстовое поле. Я хочу "передать" информацию с первой вкладки на вторую по нажатию кнопки. Просто чтобы она туда скопировалась. Как идеологически правильно это делать? Что там? Сигналы? Функции?
Я пытался написать это, используя сигналы, но оказывается, каждый таб это экземпляр отдельного класса, значит сигналы должны идти между объектами разных классов.
Желательно было бы увидеть в конце концов не только схему, но и саму рабочую программу.