
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.52] |
![]() |
|
Сообщ.
#1
,
|
|
|
Есть некоторое GUI-шное приложение. И в нём при нажатии на одну кнопку происходит вызов диалога, который эмулирует консольное окно. На этом диалоге расположен компонент типа класса Console, который является потомком класса QPlainTextEdit:
![]() ![]() class Console : public QPlainTextEdit В это текстовое поле должна выводиться и вводиться информация. Я нашёл такой способ эмуляции консольного окна: habr.com/ru/articles/122831/ С выводом информации и с обработкой нажатия клавиш всё ясно. Но как быть с вводом информации? То есть, например, в текстовое поле было выведено "Введите первое число: " , а как потом сделать ожидание ввода (аналог функций scanf, getstr или _getch в консольных приложениях)? То есть как сделать так, чтобы программа ожидала бы ввода какой-то строки и последующего нажатия клавиши Return (Enter)? А после этого программа снова вывела бы другую надпись, например "Введите второе число: " и снова ожидало бы ввода строки? Как всё это можно сделать? |
Сообщ.
#2
,
|
|
|
Раз с обработкой нажатия клавиш все ясно, тогда в чем проблема то? Обрабатывайте нажатия, пока не получите значения клавиши Enter.
|
Сообщ.
#3
,
|
|
|
Цитата erslgoeirjh @ Как всё это можно сделать? Прочитай про установку фильтров событий в Qt. В той статье, что ты указал - там как раз об этом говорится. Да, получится очень жалкое подобие эмуляции терминала. Но нормальная эмуляция - вопрос очень не простой. Посмотри проект "нормального" эмулятора терминала - ConEmu, и сам зацени уровень сложности. |
![]() |
|
|
Если правильно понял:
Для ожидания ввода строки и последующего нажатия клавиши Return (Enter) в текстовом поле QPlainTextEdit можно использовать сигналы и слоты в Qt. Следующий пример показывает, как это можно сделать: ![]() ![]() // Создаем слот для обработки нажатия клавиши Return (Enter) void Console::onReturnPressed() { // Получаем текст из текстового поля QString inputText = this->toPlainText(); // Очищаем текстовое поле this->clear(); // Обрабатываем введенную строку (например, выводим ее на экран) qDebug() << "Input: " << inputText; // Выводим следующую надпись this->appendPlainText("Введите второе число: "); } // В конструкторе класса Console подключаем сигнал editingFinished() к слоту onReturnPressed() Console::Console(QWidget *parent) : QPlainTextEdit(parent) { connect(this, &QPlainTextEdit::editingFinished, this, &Console::onReturnPressed); this->appendPlainText("Введите первое число: "); this->setFocus(); // Устанавливаем фокус на текстовое поле } В данном примере, при нажатии клавиши Return (Enter) в текстовом поле, сигнал editingFinished() будет вызван и связанный с ним слот onReturnPressed() будет выполнен. Внутри слота onReturnPressed() можно получить текст из текстового поля, очистить его и обработать введенную строку. Затем можно добавить следующую надпись в текстовое поле и ожидать ввода следующей строки. |
Сообщ.
#5
,
|
|
|
Я написал:
1) класс Console: ![]() ![]() class Console : public QPlainTextEdit { public: explicit Console(QWidget *parent=nullptr); explicit Console(const QString &text, QWidget *parent=nullptr); virtual ~Console(); void output(QString s); protected: void mousePressEvent(QMouseEvent *); void keyPressEvent(QKeyEvent *event); void onEnter(); public: bool isLocked; }; void Console::keyPressEvent(QKeyEvent *event) { if (isLocked==true) return; if ((event->key()>=0x20)&&(event->key()<=0x7e)&&((event->modifiers()==Qt::NoModifier)||(event->modifiers()==Qt::ShiftModifier))) QPlainTextEdit:;keyPressEvent(event); if ((event->key==Qt::Key_Return)&&(event->modifiers()==Qt::NoModifier)) onEnter(); } void Console::onEnter() { textCursor().insertBlock(); isLocked = true; } void Console::output(QString s) { textCursor().insertBlock(); textCursor().insertText(s); isLocked = false; } 2) класс ConsoleWindow--класс диалогового окна, который содержит на себе компонент plainTextEdit типа Console: ![]() ![]() void ConsoleWindow::print(char* s) { QString myString; myString = QString(s); ui->plainTextEdit->output(myString); } void ConsoleWindow::getstr(char *s) { string stdstr; QString myString; isEntered = false; while (isEntered==false) { if (ui->plainTextEdit->isLocked==true) isEntered = true; } QTextCursor textCursor = ui->plainTextEdit->textCursor(); QTextBlock textBlock = textCursor.block(); myString = textBlock.text(); stdstr = myString.toStdString(); strcpy(s,stdstr.c_str()); } 3) в классе MainWindow, соответствующему главному диалоговому окну приложения: ![]() ![]() void MainWindow::on_pushButton_clicked() { char s[80], s1[80], s2[80], s3[80], s4[80]; double val1, val2, val3; ConsoleWindow *consoleWindow = new ConsoleWindow(this); consoleWindow->mainWindow = this; consoleWindow->show(); strcpy(s,"Введите первое вещественное число: \n"); consoleWindow->print(s); consoleWindow->getstr(s1); // ... } В результате чего при отладке программы действия с выводом и вводом данных в ConsoleWindow "зависают"--само окно ConsoleWindow с компонентом plainTextEdit выводится, то там не отображается строка "Введите первое вещественное число" и нет ожидания ввода последующей строки. В чём причина этого? Можно ли как-то сделать так, чтобы заработало ожидание ввода строки из plainTextEdit и сам этот ввод? |
Сообщ.
#6
,
|
|
|
Ура, заработало!
Код: 1) файл console.h : ![]() ![]() #include <QObject> #include <QPlainTextEdit> class Console : public QPlainTextEdit { Q_OBJECT public: explicit Console(QWidget *parent=nullptr); explicit Console(const QString &text, QWidget *parent=nullptr); virtual ~Console(); void output(QString s); void sendSignal(); protected: void mousePressEvent(QMouseEvent *); void keyPressEvent(QKeyPressEvent *event); signals: void lineEntered(); }; 2) в файле console.cpp : ![]() ![]() void Console::keyPressEvent(QKeyEvent *event) { if ((event->key()>=0x20)&&(event->key()<=0x7e)&&((event->modifiers()==Qt::NoModifier)||(event->modifiers()==Qt::ShiftModifier))) QPlainTextEdit::keyPressEvent(event); if (((event->key()==Qt::Key_Backspace)||(event->key()==Qt::Key_Left)||(event->key()==Qt::Key_Right))&&(event->modifiers()==Qt::NoModifier)) QPlainTextEdit::keyPressEvent(event); if ((event->key()==Qt::Return)&&(event->modifiers()==Qt::NoModifier)) { sendSignal(); QPlaintTextEdit::keyPressEvent(event); } } void Console::output(QString s) { appendPlainText(s); } void Console::sendSignal() { emit lineEntered(); } 3) файл consolewindow.h : ![]() ![]() #include <QDialog> #include "mainwindow.h" #include "ui_mainwindow.h" namespace Ui { class ConsoleWindow; } class ConsoleWindow : public QDialog { Q_OBJECT public: explicit ConsoleWindow(QWidget *parent=nullptr); ~ConsoleWIndow(); private slots: void on_pushButton_2_clicked(); public slots: void onEnter(); private: Ui::ConsoleWIndow *ui; public: void print(char* s); void getstr(char* s); int curlength; char mystr[80]; MainWindow *mainWindow; QEventLoop loop; }; 4) в файле consolewindow.cpp : ![]() ![]() void ConsoleWindow::print(char* s) { QString myString; myString = QString(s); ui->plainTextEdit->output(myString); } void ConsoleWindow::getstr(char *s) { int index, length; string stdstr; QString myString; connect(ui->plainTextEdit,SIGNAL(lineEntered()),this,SLOT(onEnter())); loop.exec(); myString = ui->plainTextEdit->toPlainText(); length = myString.length(); myString = myString.left(length-1); index = myString.lastIndexOf('\n'); myString = myString.right(length-index-2); stdstr = myString.toStdString(); strcpy(s,stdstr.c_str()); disconnect(ui->plainTextEdit,SIGNAL(lineEntered()),this,SLOT(onEnter())); } void ConsoleWindow::onEnter() { loop.exit(); } 5) в файле mainwindow.cpp : ![]() ![]() void MainWindow::on_pushButton_clicked() // если была нажата кнопка "Тестировать" { char s[80], s1[80], s2[80], s3[80], s4[80], sanswer[10]; double val1, val2, val3; ConsoleWindow *consoleWindow = new ConsoleWIndow(this); consoleWindow->mainWindow = this; consoleWindow->show(); metka: ; strcpy(s,"Введите первое вещественное число:\n"); consoleWindow->print(s); consoleWindow->getstr(s1); strcpy(s,"Введите второе вещественное число:\n"); consoleWindow->print(s); consoleWindow->getstr(s2); val1 = atof(s1); val2 = atof(s2); val3 = val1 + val2; sprintf(s3,"%f",val3); sprintf(s4,"Сумма введённых двух чисел равна: "); strcat(s4,s3); consoleWindow->print(s4); strcpy(s,"Будете ещё работать (y/n)?\n"); consoleWindow->print(s); consoleWIndow->getstr(sanswer); if (((strcmp(sanswer,"y")==0)||(strcmp(sanswer,"Y")==0))) goto metka; consoleWindow->close(); } |