Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Написание чата
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt GUI
breeve
я в qt дуб дубом.. Такой вопрос. вот взять например любой чат.. как называется такой виджет что-то вроде textedit только в который нельзя вводить.
Вообщем мне необходимо сделать программу в виде чата.. внизу вводишь нажимаешь ентер и выводиться сверху вот так:
Цитата
> Я ввел это предложение
MoPDoBoPoT
Это называется QTextEdit (или QPlainTextEdit для простого текста) со свойством readOnly=true :)
breeve
Цитата(MoPDoBoPoT @ 26.12.2009, 21:45) *
Это называется QTextEdit (или QPlainTextEdit для простого текста) со свойством readOnly=true :)

я конечно предполагал что оно именно так.. но я чето понятия не имею как ставить этот параметр
а за своевременный ответ пасиба!!
MoPDoBoPoT
Есть метод QTextEdit::setReadOnly(bool readOnly). Вся информация по классам описана в QtAssistant, там и всевозможные примеры есть. А вообще, лучше начать с книжки для новичка, типо "Макс Шлее - Qt 4.5. Профессиональное программирование на C++". Займет день-два, а пользы...
breeve
Цитата(MoPDoBoPoT @ 26.12.2009, 22:07) *
Есть метод QTextEdit::setReadOnly(bool readOnly). Вся информация по классам описана в QtAssistant, там и всевозможные примеры есть. А вообще, лучше начать с книжки для новичка, типо "Макс Шлее - Qt 4.5. Профессиональное программирование на C++". Займет день-два, а пользы...

чесно говоря у меня есть эта книга.. я многое там прочитал.. теоретически я знаю.. а написать что-то я не могу..
MoPDoBoPoT
Ну и Москва не сразу строилась. По чуть-чуть наполняй функционалом программу, и освоишься. Главное проникнуться основной идеей.
На начальном этапе еще не рекомендуется пользоваться визульной средой разработки (QtDesigner), чтобы "набить руки".
breeve
Цитата(MoPDoBoPoT @ 26.12.2009, 22:36) *
Ну и Москва не сразу строилась. По чуть-чуть наполняй функционалом программу, и освоишься. Главное проникнуться основной идеей.
На начальном этапе еще не рекомендуется пользоваться визульной средой разработки (QtDesigner), чтобы "набить руки".


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

Цитата(breeve @ 26.12.2009, 22:42) *
Цитата(MoPDoBoPoT @ 26.12.2009, 22:36) *
Ну и Москва не сразу строилась. По чуть-чуть наполняй функционалом программу, и освоишься. Главное проникнуться основной идеей.
На начальном этапе еще не рекомендуется пользоваться визульной средой разработки (QtDesigner), чтобы "набить руки".


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


вот нашел примерчик.. прям что надо.. два текстедита разделенных splitter'ом.. вот а как сделать так чтобы вниз писал вверх выводил..
Litkevich Yuriy
breeve, два учебных пособия на русском языке - тыц
breeve
Цитата(Litkevich Yuriy @ 26.12.2009, 23:08) *
breeve, два учебных пособия на русском языке - тыц

Спасибо конечно.. но я их делал)

Вопрос конечно понимаю тупой..
вот код:
Раскрывающийся текст
#include <QtGui>
//#include "chat.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSplitter sp1(Qt::Vertical);
    QTextEdit *ptxt1 = new QTextEdit;
    QTextEdit *ptxt2 = new QTextEdit;

    sp1.addWidget(ptxt1);
    sp1.addWidget(ptxt2);

    ptxt1->setPlainText("Line 1\n"
                        "Line 2\n");
    ptxt1->setReadOnly(1);
    sp1.resize(200, 220);
    sp1.show();
    return a.exec();
}


Как сделать так чтобы я писал в ptxt2 нажимал ентер а он выводил сверху?
MoPDoBoPoT
Цитата(breeve @ 26.12.2009, 22:43) *
вот а как сделать так чтобы вниз писал вверх выводил..

Я сам не особый знаток, но мне кажется, что надо работать с объектом документом имеющегося текстэдита.
Методом QTextEdit::document() получаем указатель на документ, а дальше добавляем ему в начало необходимый текс.
Например:
...
QString myText;
...
QTextDocument *doc = textEdit->document();
doc->setPlainText(myText + doc->toPlainText());
...

Возможно есть более шустрый код, я с QTextDocument и прочим не разбирался.
Litkevich Yuriy
Цитата(breeve @ 27.12.2009, 2:17) *
Как сделать так чтобы я писал в ptxt2 нажимал ентер а он выводил сверху?
в одной функции main ты этого не сделаешь
MoPDoBoPoT
Цитата(breeve @ 26.12.2009, 23:17) *
Спасибо конечно.. но я их делал)

Хех. Делал - это как? Собрал проект, потыркался в проге и все? :)
Цитата(breeve @ 26.12.2009, 23:17) *
Как сделать так чтобы я писал в ptxt2 нажимал ентер а он выводил сверху?

Без наследования никак.
Разберись с сигнал-слотами. В книге у Шлее есть на эту тему простенький пример "Counter".
Litkevich Yuriy
тебе нужно создать класс-окно. Т.е. делаешь наследника от QWidget, в него помещаешь почти всё содержимое main.
У QTextEdit есть сигнал textChanged() и есть слоты:
selectAll()
cut ()
paste ()

идея такая:
соеденяешь сигнал textChanged() QTextEdit'а нижнего со слотом своего окна (надо его создать)
В слоте делаешь последовательно для этого QTextEdit'а
textedit1->selectAll()
textedit1->cut ()
и вставляешь во второй:
textedit2->paste ()
breeve
ну допустим как вывести это я более или менее понял посмотрел про qtextdoc в ассистенте..
Как забиндить ентер.. и как мне считать с textedit'а
вот допустим setPlainText как я понял вставляет туда текст.. А есть ли getPlainText))?

Цитата(breeve @ 26.12.2009, 23:35) *
ну допустим как вывести это я более или менее понял посмотрел про qtextdoc в ассистенте..
Как забиндить ентер.. и как мне считать с textedit'а
вот допустим setPlainText как я понял вставляет туда текст.. А есть ли getPlainText))?

Чет не заметил я вторую страничку..
breeve
Цитата(Litkevich Yuriy @ 26.12.2009, 23:29) *
тебе нужно создать класс-окно. Т.е. делаешь наследника от QWidget, в него помещаешь почти всё содержимое main.
У QTextEdit есть сигнал textChanged() и есть слоты:
selectAll()
cut ()
paste ()

идея такая:
соеденяешь сигнал textChanged() QTextEdit'а нижнего со слотом своего окна (надо его создать)
В слоте делаешь последовательно для этого QTextEdit'а
textedit1->selectAll()
textedit1->cut ()
и вставляешь во второй:
textedit2->paste ()


Алгоритм я понял.. вот сделал как сказали..
Переделал все под класс.. только что мне писать в объявлении TextChanged(), selectAll(), cut(), и paste()?

breeve
Насчет TextChanged(), .. как я понял они стандартные.. и объявлять их не нужно.. Я тут нашел в книге про textEdit правда мало очень..
такой вопрос как забиндить клавишу? Вот этот textChanged() высылается при изменении текста.. если я сделаю в точности как сказал Litkevich Yuriy, у меня будет так: я печатаю букву "у" - текст изменился, он его весь выделил, вставил вверх.. печатаю след букву "м" происходит тоже самое.. и получается как зеркало что здесь то и там.. Если я конечно правильно понял.. Но мне надо не так.. мне надо чтобы я напечатал, нажал, он как приплюсовал к строке то что я тока что ввел.. т.е было:
> Привет. // я ввел "Хай!" и нажал ентер и получилось

> Привет.
> Хай!
breeve
вот решил пока не заморачиваться насчет ентера сделать кнопку. вот код
main.cpp
#include <QtGui/QApplication>
#include "button.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Button wgt;
    

    wgt.show();
    
    return a.exec();
}

button.cpp
#include "button.h"

Button::Button(QWidget *parent)
    : QWidget(parent)
{
    QTextEdit *ptxt1 = new QTextEdit;
    QTextEdit *ptxt2 = new QTextEdit;
    QPushButton *cmd = new QPushButton("Add");

    QHBoxLayout * MyHLayout = new QHBoxLayout;
    QVBoxLayout * MyVLayout = new QVBoxLayout;

    MyHLayout->setMargin(10);
    MyHLayout->setSpacing(20);
    MyHLayout->addWidget(ptxt2);
    MyHLayout->addWidget(cmd);

    MyVLayout->addWidget(ptxt1);
    MyVLayout->addLayout(MyHLayout);
    setLayout(MyVLayout);

    setWindowTitle("Test Chat");
    setGeometry(5,5, 200, 100);
    
    connect(cmd, SIGNAL(clicked()),
                     SLOT(mySlot())
                     );
}

void Button::mySlot()
{
    ptxt1->selectAll();
    ptxt1->cut();
    ptxt2->paste();
}

button.h
#ifndef BUTTON_H
#define BUTTON_H

#include <QtGui>

class Button : public QWidget
{
    Q_OBJECT

public:
    QTextEdit *ptxt1;
    QTextEdit *ptxt2;
    QPushButton *cmd;
    QHBoxLayout *MyHLayout;
    QVBoxLayout *MyVLayout;
    
    Button(QWidget *parent = 0);
    ~Button() {};
public slots:
    void mySlot();
};

#endif // BUTTON_H


Ввожу что-нибудь нажимаю на кнопку.. он виснет)
Litkevich Yuriy
зря ты класс назвал "кнопкой", ведь на кнопке нет полей ввода и т.д.
breeve
Цитата(Litkevich Yuriy @ 27.12.2009, 16:15) *
зря ты класс назвал "кнопкой", ведь на кнопке нет полей ввода и т.д.

А какая разница как он назван? он же не является кнопкой то по сути...
Litkevich Yuriy
для отладки в слот вставь qDebug(), например:
void Button::mySlot()
{
    qDebug() << "mySlot";
    ptxt1->selectAll();
    qDebug() << "selectAll";
    ptxt1->cut();
    qDebug() << "cut";
    ptxt2->paste();
    qDebug() << "paste";
}
в pro-файл, добавь:
CONFIG += console
тогда в консоль, при отладочной сборке будут печататься эти строчки, так ты сможешь локализовать проблему.

Цитата(breeve @ 27.12.2009, 19:17) *
А какая разница как он назван? он же не является кнопкой то по сути...
существенная, когда читаешь чужой код, а его милион строк может быть, то ориентируешся на имена. Я смотрю main.cpp, и не понимаю, а где у breeve окно, кнопку вижу, а дальше?
breeve
вставил как вы сказали получилось вот так:
Раскрывающийся текст
#include "button.h"

Button::Button(QWidget *parent)
    : QWidget(parent)
{
    QTextEdit *ptxt1 = new QTextEdit;
    QTextEdit *ptxt2 = new QTextEdit;
    QPushButton *cmd = new QPushButton("Add");

    QHBoxLayout * MyHLayout = new QHBoxLayout;
    QVBoxLayout * MyVLayout = new QVBoxLayout;

    MyHLayout->setMargin(10);
    MyHLayout->setSpacing(20);
    MyHLayout->addWidget(ptxt2);
    MyHLayout->addWidget(cmd);

    MyVLayout->addWidget(ptxt1);
    MyVLayout->addLayout(MyHLayout);
    setLayout(MyVLayout);

    setWindowTitle("Test Chat");
    setGeometry(5,5, 200, 100);
    
    connect(cmd, SIGNAL(clicked()),
            this, SLOT(mySlot())
                     );

}

void Button::mySlot()
{
    qDebug() << "mySlot";
    ptxt1->selectAll();
    qDebug() << "selectAll";
    ptxt1->cut();
    qDebug() << "cut";
    ptxt2->paste();
    qDebug() << "paste";

}


Теперь он у меня просто выходит по нажатию кнопки и все.
А консоль просмотреть где можно? Пишу на Креаторе..
Litkevich Yuriy
Цитата(breeve @ 27.12.2009, 19:28) *
Пишу на Креаторе..
ну где-то там снизу есть консоль, я не в курсе
breeve
Снизу есть окошко называется Application Output:
Цитата
Starting /home/breeze/.qtProjects/button_two/button_two...
mySlot

The program has unexpectedly finished.

/home/breeze/.qtProjects/button_two/button_two exited with code 0

Вот что там выводится
BRE
Измени конструктор:
Раскрывающийся текст
#include "button.h"

Button::Button(QWidget *parent)
    : QWidget(parent)
{
    ptxt1 = new QTextEdit;
    ptxt2 = new QTextEdit;
    cmd = new QPushButton("Add");

    QHBoxLayout * MyHLayout = new QHBoxLayout;
    QVBoxLayout * MyVLayout = new QVBoxLayout;

    MyHLayout->setMargin(10);
    MyHLayout->setSpacing(20);
    MyHLayout->addWidget(ptxt2);
    MyHLayout->addWidget(cmd);

    MyVLayout->addWidget(ptxt1);
    MyVLayout->addLayout(MyHLayout);
    setLayout(MyVLayout);

    setWindowTitle("Test Chat");
    setGeometry(5,5, 200, 100);
    
    connect(cmd, SIGNAL(clicked()),
            this, SLOT(mySlot())
                     );

}

и все заработает. ;)
Litkevich Yuriy
Цитата(BRE @ 27.12.2009, 19:42) *
Измени конструктор:
Да, правда.
breeve
да все заработало.. Но есть одно неудобство.. он вставляет не в верхнее окно, а в нижнее..
т.е пишу ляля, нажимаю add и снизу получается:
ляляляля
))

нене.. гоню.. он вставляет не то что я туда ввел а то что сейчас у меня в буфере обмена..

Ооо.. Всем спасибо.. я поменял название textEdit'ов и все заработало))
Litkevich Yuriy
Цитата(breeve @ 27.12.2009, 19:49) *
а то что сейчас у меня в буфере обмена..
угу.
Я привёл простейший способ. Теперь тебе нужно усовершенствовать код. Брать текст явно из QTextEdit'а, и явно его помещать в другой.

breeve, ты понял суть ошибки в конструкторе?
breeve
Цитата(Litkevich Yuriy @ 27.12.2009, 16:54) *
Цитата(breeve @ 27.12.2009, 19:49) *
а то что сейчас у меня в буфере обмена..
угу.
Я привёл простейший способ. Теперь тебе нужно усовершенствовать код. Брать текст явно из QTextEdit'а, и явно его помещать в другой.

breeve, ты понял суть ошибки в конструкторе?

Понял, я создавал текстЕдит как новый не тот что я объявлял в хидере..
Ага а усовершенствовать это да.. Мне бы еще узнать как биндить клавишу ентер и все будет отлично)
Litkevich Yuriy
Цитата(breeve @ 27.12.2009, 19:58) *
Мне бы еще узнать как биндить клавишу ентер и все будет отлично)
оставь её на потом. А сейчас займись, тем, без чего чат не чат. Т.е. корректным отображением текста в журнальном поле (верхнем), чтобы там и символ ">" был и копирование было без буфера обмена.


По поводу перехвата клавиши "Enter" - это отдельная тема, она достаточно независима. Мало того тема такая поднималась.
breeve
Только еще я не очень понимаю как явно передать из одного другому не через буфер..
Т.е как я думаю, это значит присвоить какой-нибудь строке содержимое первого текст едита..
потом во втором просто вывести эту строку)
можно ли сделать так:
QString str=ptxt1 -> text();
ptxt2 ->insertPlainText(str);
BRE
Посмотри на void QTextEdit::append ( const QString & text ) [slot]
breeve
Отлично все сделал!!
вот так:
    QString str = ptxt2->toPlainText();
    ptxt1->insertPlainText("> ");
    ptxt1->insertPlainText(str);
    ptxt1->insertPlainText("\n");
BRE
Для чего делать три вызова метода, если достаточно одного:
    QString str = ptxt2->toPlainText();
    ptxt1->insertPlainText( QString( "> " ) + str + "\n" );
    // или
    ptxt1->insertPlainText( QString( "> %1\n" ).arg( str ) );

breeve
У меня назрел еще вопрос можно ли использовать стандартные директивы сишные.. например string.. или обязательно надо использовать их Qt'ешные аналоги?
Вот мне необходимо использовать функцию вхождения строки А в строку Б.. В стандартной директиве я знаю какую функцию мне использовать.. А здесь нет..
BRE
Цитата(breeve @ 27.12.2009, 17:43) *
У меня назрел еще вопрос можно ли использовать стандартные директивы сишные.. например string.. или обязательно надо использовать их Qt'ешные аналоги?
Вот мне необходимо использовать функцию вхождения строки А в строку Б.. В стандартной директиве я знаю какую функцию мне использовать.. А здесь нет..

Почитай про класс QString. Там функционала с избытком. ;)
breeve
вот нашел функцию QString::contains()
и она мне всегда говорит 0.
Не понимаю вот код:
    int count = 0;
    QString str = ptxt2->toPlainText();
    if(str.contains("Привет")==1)
        count = 1;
    qDebug() << count;
    if(count == 1)
    {
        ptxt1->insertPlainText("Bot: H1\n");
        count = 0;
    }
BRE
Цитата(breeve @ 27.12.2009, 18:02) *
вот нашел функцию QString::contains()
и она мне всегда говорит 0.
if(str.contains("Привет")==1)

Все правильно, почитай в assistant про то, как в Qt хранятся строки, про QTextCodec и локализацию. С этим нужно разобраться сразу и тогда масса вопросов отпадет сама собой. :)
breeve
Я даже понял в чем проблема, только не знаю как решить ее
Когда я ввожу с клавиатуры.. там видимо кодировка другая и поэтому он не определяет.. с цифрами и с латинским алфавитом работает а вот с русским(((
Как мне переделать строку под определенную кодировку ?

не успеваю задать вопрос уже ответ написали))
Litkevich Yuriy
Цитата(breeve @ 27.12.2009, 21:09) *
Как мне переделать строку под определенную кодировку ?
надо строковые константы перевести в QString, в функции main:
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); // Для функций перевода tr()
вместо UTF-8 укажи кодировку, в которой сам исходник пишется.

Далее в коде оборачивай строковые константы в функцию tr:
tr("Привет")
breeve
Цитата(Litkevich Yuriy @ 27.12.2009, 18:14) *
Цитата(breeve @ 27.12.2009, 21:09) *
Как мне переделать строку под определенную кодировку ?
надо строковые константы перевести в QString, в функции main:
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); // Для функций перевода tr()
вместо UTF-8 укажи кодировку, в которой сам исходник пишется.

Далее в коде оборачивай строковые константы в функцию tr:
tr("Привет")



вот эта функция tr() она принимает на значение const char*, так? а мне же надо перевести QString в другую кодировку.. А ты мне пишешь "Надо строковые константы перевести в QString".. помоему как раз таки наоборот.. QString в const char..



Я видимо не так понял)) Подставил tr под "привет" и все заработало)) Спасибо
Litkevich Yuriy
просто константа "Привет" будет превращена в QString, с его внутренним представлением, из кодировки которую ты указваешь глобально в main'е.

А дальше при сравнении двух QString, сравниваться уже будут строки в одной и тоже внутренней кодировке Qt (UTF-16)
breeve
Цитата(Litkevich Yuriy @ 27.12.2009, 19:15) *
просто константа "Привет" будет превращена в QString, с его внутренним представлением, из кодировки которую ты указваешь глобально в main'е.

А дальше при сравнении двух QString, сравниваться уже будут строки в одной и тоже внутренней кодировке Qt (UTF-16)


Да это конечно все хорошо.. все понятно, все работает..
Я на самом деле думал что будет не одна строка "Привет" а допустим массив QString где много разных привет и допустим если введенное слово совпадает со словом из одного массива то пишет одно, из другого другое.. Так вот а tr() не хочет принимать QString на параметр.. пишет ошибку

А насчет Ентера нашел тут вот тему прошлогоднюю и там был код я его малец переделал:
   qatmp = new QAction(this);
    qatmp->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Return));
    connect(qatmp,SIGNAL(triggered()), this,SLOT(mySlot()));
    addAction(qatmp);

Вставил он работает.. только мне нужно чтобы не комбинацию считывал, а одну кнопку.. я пытался убрать альт и оставить только ентер вот так: (Qt::Key_Return)
он у меня так не работает.. Искал в документацию как забиндить одну кнопку что-то так и не нашел(
Litkevich Yuriy
Цитата(breeve @ 27.12.2009, 22:44) *
ак вот а tr() не хочет принимать QString на параметр.. пишет ошибку
а зачем ему принимать QString, он тебе QString'ов делает, их и используй.

Цитата(breeve @ 27.12.2009, 22:44) *
Вставил он работает.. только мне нужно чтобы не комбинацию считывал, а одну кнопку.. я пытался убрать альт и оставить только ентер вот так: (Qt::Key_Return)
посмотри тему: перемещение курсора в QTextEdit, там есть обработка события нажатия клавиши "Enter". Если будет не достаточно создай новую, уточняющую тему, или наоборот более общую.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.