Бесконечный цикл -> Нужно показать главный экран с Qt

вот я снова! Итак, я разрабатываю эмулятор GBC на С++, но у меня есть некоторые проблемы. Прежде всего, я использую Qt в VS10, который до сих пор работает хорошо. Но у меня есть графический интерфейс (главное окно) с несколькими объектами (QListWidget, кнопки и т. д.). Итак, в моем классе ЦП у меня есть цикл, который эмулирует все инструкции GBC. Это работает простым способом. Получите код, декодируйте, извлеките и вызовите операцию в коммутаторе, сделайте это снова и снова. Итак, моя проблема в том, что при каждом взаимодействии я хотел бы, чтобы этот главный экран отображался с обновленным списком.

Изображение ниже, я не могу опубликовать, потому что у меня нет 10 очков повторения. http://i.stack.imgur.com/BdaHo.png

Итак, кусок кода, чтобы вы могли (попробовать?) понять, что происходит: (cpu.cpp)

next:
op = FETCH;
setSelection((UINT32)op);
ciclos = cycles_table[op];

switch(op)
{
       do the magic
       emit onEndProcess((UINT32)op);
       goto next;
}

процессор.ч

signals:
void onEndProcess(UINT32);

который получает ratagbc (ratagbc.h)

public slots:
        void receivedEndProcess(UINT32);

И реализовано:

void RataGBC::receivedEndProcess(UINT32 i){
    this->ui.listWidget->item(i+1)->setSelected(true);
    this->show();
 }

И в конструкторе рата после ui.setupUI(...) у меня есть:

cpp = new cpu();
    connect(cpp,SIGNAL(onEndProcess(UINT32)),this,SLOT(receivedEndProcess(UINT32)));

}

Где cpp — это экземпляр класса процессора. Здесь есть проблема, это подключение возвращает false !!

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
RataGBC w;
dasm dsm;
FILE *file = fopen("Tetris DX.gbc","r");
int c = 0;
while(dsm.DAsm(file,w.ui.listWidget,c));
fclose(file);
w.cpp->start();
w.show();
return a.exec();
}

Одна вещь, которую я заметил, это то, что мне нужно реализовать (пустой) onEndProcess в моем cpu.cpp, или это дает мне ошибку связывания. Это действительно необходимо?

Надеюсь, вы, ребята, понимаете, что мне нужно! Спасибо !


person Leonardo    schedule 29.02.2012    source источник


Ответы (3)


a.exec() запускает цикл событий, который включает обновление графического интерфейса. Поместите соответствующие шаги в функцию и используйте систему событий Qt для выполнения кода.

И не используйте goto.

person tmpearce    schedule 29.02.2012
comment
Я не понял, что ты имеешь в виду. Должен ли я передавать QApplication в качестве параметра процессору? Какие шаги? Спасибо ! - person Leonardo; 29.02.2012

Используйте QTimer с тайм-аутом 0 для выполнения обработки бездействия.
Создайте QObject (сохраните в нем свой «эмулируемый процессор») со слотом, подключите его к сигналу таймера и в этом слоте обработайте один шаг программы (RagaGBC) за время. т.е. выполнить один шаг вашей эмулируемой программы. Или несколько шагов, просто не все. Запустите таймер для запуска эмулируемой программы.
Когда вы закончите, вызовите QCoreApplication::exit();.

Если вы не понимаете, как создавать QObject/использовать таймеры, прочитайте руководства по Qt.

person SigTerm    schedule 29.02.2012

Вы пытаетесь запустить два «бесконечных цикла» в одном потоке. Один из них — это ваш цикл ЦП, который, очевидно, блокируется. Другой — это цикл обработки событий Qt, который будет блокироваться до тех пор, пока вы не выйдете из приложения.

Я могу ошибаться здесь, так как я никогда раньше не реализовывал эмулятор ЦП, но — хотя это возможно — я думаю, что вам не следует запускать цикл ЦП в том же потоке, что и графический интерфейс, поскольку ЦП напряжен и, возможно, чувствителен к временным колебаниям. .

Вместо этого следует запускать ЦП в отдельном потоке и взаимодействовать с потоком графического интерфейса с помощью слоты в очереди и другие многопоточные конструкции, такие как QMutex, QAtomicInt и QAtomicPointer.

Вот как я бы это реализовал (очевидно, вам следует его адаптировать):

Поток графического интерфейса пользователя

Здесь вы запускаете QApplication::exec().

  • Построить главное окно (со списком и областью рисования)
  • Запустите поток процессора
  • Всякий раз, когда происходит событие ввода, сигнализируйте об изменении в потоке ЦП.
  • Всякий раз, когда поток ЦП обновляет видеобуфер, обновляет поверхность рисования
  • Когда пользователь уйдет, остановите поток ЦП

Поток ЦП

Реализуйте новый QThread, чтобы сделать следующее.

  • Получить, декодировать, выполнить
  • Читать ввод всякий раз, когда он обновляется
  • Запишите видеопамять и уведомите поток графического интерфейса, чтобы обновить поверхность рисования.
  • Выйти, когда скажут.

Помните, что только поток GUI может манипулировать такими виджетами пользовательского интерфейса, как списки и меню. Поток ЦП должен использовать такие механизмы, как слоты в очереди, чтобы сообщать потоку графического интерфейса об обновлении виджетов.

Еще один совет: посмотрите как другие люди решили ту же проблему.

person andref    schedule 29.02.2012
comment
Почему этот пост получил -1? Хотя у меня нет знаний, чтобы судить, является ли это лучшим возможным ответом, подход andref кажется, по крайней мере, разумным. Таким образом, может быть, кто-то может помочь мне понять, где плохое качество выше... - person Thilo; 01.03.2012
comment
@Thilo: Потому что это излишне сложно, а чрезмерно сложное решение приведет к пустой трате времени на разработку, что будет стоить времени и денег. Помните о принципе KISS. Работа программиста состоит не в том, чтобы предложить самое сложное решение, а в том, чтобы предложить самое дешевое. В этом случае действительно нет необходимости в другом потоке и возможных проблемах/ошибках синхронизации, которые обязательно последуют. Без потоков вы можете реализовать все это в 20 строках кода или меньше. - person SigTerm; 01.03.2012
comment
Это верная точка зрения. Однако я уточнил свой ответ: запуск ЦП и графического интерфейса в одном потоке подвергнет ЦП колебаниям времени цикла событий. Если точность не является проблемой, мое предложение действительно немного излишне. Тем не менее, многопоточное программирование в Qt довольно простое, особенно с использованием конструкций, предоставляемых библиотекой. - person andref; 01.03.2012
comment
@andref Я пытался сделать то, что ты предложил, но когда я пытаюсь соединить сигнал и слот, он продолжает возвращать false. Собираюсь отредактировать мой код, чтобы увидеть, как это. Спасибо ! - person Leonardo; 01.03.2012
comment
Никто ? Спасибо и извините за беспокойство! - person Leonardo; 02.03.2012
comment
Вы имеете в виду, что соединение возвращает false? Сигнатуры сигнала и слота совпадают? Вы добавили Q_OBJECT в классы? - person andref; 03.03.2012
comment
@andref Мне удалось заставить это работать (соединение), но теперь я столкнулся с другой проблемой. Мое получение от соединения выглядит следующим образом: void RataGBC::receivedEndProcess(UINT32 i){ this-›ui.listWidget-›item(i+1)-›setSelected(true); this-›ui.statusBar-›showMessage(QString::number(i)); //this-›ui.listWidget_2-›addItem(QString::number(cpp-›getCpu(),16)); QCoreApplication::processEvents(); }. Я пока не вижу. Какие функции я должен вызывать в своем Receive? Есть идеи ? Спасибо - person Leonardo; 04.03.2012
comment
Является ли ваш код общедоступным в Github, Bitbucket или где-то еще? Я думаю, у нас слишком мало контекста, чтобы помочь вам. - person andref; 05.03.2012
comment
Я сделаю это доступным на Github! Спасибо за чаевые ! - person Leonardo; 06.03.2012
comment
@andref вот оно, чувак. Я попытался изменить некоторые вещи, такие как подключение к моей основной сети (подключение потока к процессору), но это тоже не работает. Спасибо за помощь ! github.com/leonardo2204/Rata-GBC - person Leonardo; 07.03.2012