Evgenii Legotckoi
Evgenii LegotckoiСәуір 21, 2018, 4:18 Т.Қ.

Qt/C++ - 076-сабақ. Qt-дағы математикалық формулаларды визуализациялау

Жақында форумда Qt формулаларын қалай бейнелеуге болатыны туралы өте қызықты сұрақ пайда болды. Өкінішке орай, менде сайт пен форуммен ұзақ уақыт айналысуға мүмкіндігім болмады, бірақ біраз уақыттан кейін де мәселе туралы өзімнің болжамымды ұсыну пайдалы болады деп шештім.

Сұрақ жол ретінде жазылған формуланы визуализациялау болып табылады.

Мысалы, сіз кейбір енгізу өрісіне sqrt(5) енгізесіз, ал кейбір виджетте 5 квадрат түбірінің графикалық дисплейі көрсетіледі, яғни нәтиже емес, формуланың өзі. Ұқсас функция Latex және LibreOffice-те жүзеге асырылады.

Бұл келесідей болады.

Өздігінен, мұндай функционалдылықты жазу міндеті, менің ойымша, өте қиын және көп уақытты қажет етеді, әсіресе кірістірілген формулалары бар функцияны жүзеге асыруға келгенде және т.б. Сондықтан мен формулалардың ең қарапайым нұсқаларын көрсетуді жүзеге асыру үшін менің ойыма келген тұжырымдамаға тоқталатын боламын, яғни. кірістірілген ішкі формулаларсыз.


Жалпы ережелер

Бұл функцияны іске асыру үшін сізге қажет:

  • Тұрақты өрнектерді пайдаланып, формула жазбасын бөлектеңіз
  • Виджеттегі формуланы көрсету

Бұл тапсырма үшін тұрақты өрнектерді пайдалану өте орынды болады деп ойлаймын, өйткені жолды дұрыс талдау және формулалардың даналарын бөлектеу керек. Формуланың графикалық дисплейін жасау үшін формула жолында іздеуге арналған тұрақты өрнекті, сондай-ақ формуланы көрсетілген нүктеде сызатын әдісті қамтитын FormulaWidget арнайы класын жазамыз. виджеттің өзі қамтамасыз ететін QPainter нысанын қолданатын виджет. Бұл әдіс келесі формуланы салу үшін жаңа позицияны қайтаруы керек, осылайша олар бірнеше формулалар қатарынан берілсе, олар бір-біріне сәйкес келмейді.

Формулаларды салу үшін QWidget-тен мұраланған класс жасап, оның осы виджеттің мазмұнын салуға жауап беретін paintEvent() әдісін қайта анықтайық.

Қолданбаның негізгі терезесі

QWidget-тен мұраланған класс қолданбаның негізгі терезесі ретінде пайдаланылады. Сіз оны жобаны жасаған кезде таңдайсыз. Сондай-ақ оның графикалық пішін файлы болады, оған бізді қызықтыратын виджеттерді орналастыру қажет:

  • QLineEdit - формуланы мұнда жазамыз
  • FormulaWidget - формула көрсетілетін жерде

Графикалық редакторда әдеттегі виджет нысанын қосып, оны бұрын жасалған FormulaWidget сыныбына түрлендіру үшін контекстік мәзірді пайдалану қажет. Мәтінмәндік мәзірде бұл үшін "Convert to ..." немесе ағылшын тіліндегі нұсқасында "Promote to ..." бар.

Мен main.cpp файлының мазмұнына қол тигізбеймін, себебі бәрі әдепкі бойынша жасалған.

виджет.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

widget.cpp

Терілген мәтінді формула виджеттеріне беру үшін біз FormulaWidget ішінде жасайтын QLineEdit құралының setFormula ұясына сигнал textChanged қосылымын қолданамыз. сынып.

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->lineEdit, &QLineEdit::textChanged, ui->formulaWidget, &FormulaWidget::setFormula);
}

Widget::~Widget()
{
    delete ui;
}

Формулаларды көрсетуге арналған сабақтар

Енді формулаларды визуализациялауға арналған сыныптың өзін және формуланың өзін қарастырыңыз. Бұл сыныптардың екеуі бір тақырып файлында ( FormulaWidget.h ) және іске асыру файлында ( FormulaWidget.cpp ) орналасады.

Формула элементі

FormulaWidget.h

// Класс визуализации формулы
class FormulaItem
{
public:
    explicit FormulaItem(QString value) : m_value(value){}

    static const QString REGULAR_EXPRESSION; // Строка регулярного выражения для поиска формулы
    // Метод отрисовки формулы
    QPoint draw(const QPoint& pos, QPainter& p) const;

private:
    QString m_value; // Значение формулы
};

FormulaWidget.cpp

const QString FormulaItem::REGULAR_EXPRESSION = "sqrt\\((?<value>\\d+)\\)";

QPoint FormulaItem::draw(const QPoint& pos, QPainter& p) const
{
    int valueWidth = p.fontMetrics().width(m_value);
    int valueHeight = p.fontMetrics().height();

    p.drawLine(pos.x(), 4 + valueHeight / 2, pos.x() + 5, 4 + valueHeight);
    p.drawLine(pos.x() + 5, 4 + valueHeight, pos.x() + 10, pos.y() + 1);
    p.drawLine(pos.x() + 10, pos.y() + 1, pos.x() + 14 + valueWidth, pos.y() + 1);

    p.drawText(QRect(pos.x() + 12, pos.y() + 4, pos.x() + 12 + valueWidth, pos.y() + 4 + valueHeight), m_value);
    return QPoint(pos.x() + valueWidth + 20, pos.y());
}

REGULAR_EXPRESSION статикалық тұрақты айнымалы мәні формуланың пайда болуын іздеу үшін тұрақты өрнекті қамтитын жол болып табылады.

Qt тұрақты өрнектермен жұмыс істеу үшін екі сыныпты ұсынады:

  1. QRegExp - Мен оны html белгілеу синтаксисін бөлектеуді жазу туралы мақалада қолдандым.
  2. QRegularExpression - Мен бұл туралы әлі мақала жазған жоқпын және бұл оны қолданатын бірінші мақала болмақ.

Бірінші класс бұрын енгізілді, екіншісі тек Qt 5.0-де енгізілді. Біріншісі, менің түсінуімше, Qt-тің тұрақты өрнектерді жеке жүзеге асыруы. Ал екінші класс тек Perl тіліне арналған синтаксистік қолдауы бар тұрақты өрнектерді іске асыру болып табылады. Әзірге құжаттама QRegularExpression пайдалануды ұсынады және тұрақты өрнектердің синтаксисін үйрену үшін Perl құжаттамасын зерттеңіз.

Қорқынышты сызу әдісіне келетін болсақ, оның орындалуы формуланы әдемі сызуға, квадрат түбір ішіндегі мәннің орнын орнатуға жауап береді. Сиқырлы сандар бар барлық сызықтар мен сандарды пиксель бойынша көрсету үшін псевдоматематика жеткілікті. Нақты жобаларда мұны болдырмауға тырысыңыз және PADDING_BOTTOM, OFFSET және т.б. сияқты аталған тұрақтыларды пайдаланыңыз.

draw әдісіндегі маңызды сәттердің бірі QPainter нысаны сілтеме арқылы аргумент ретінде берілуі керек, бірақ сілтеме const болуы мүмкін емес, себебі бұл нысан өзгертілетін болады. Демек, мұнда бәрі жақсы. Өз тәжірибемнен айтамын, бұл реттелетін виджеттерді көрсетумен жұмыс істеу үшін олардың QPainter басқа әдістерге тұрақты емес сілтеме арқылы берілген кезде қалыпты жағдай.

Жоғарыдағы тұрақты өрнекте кейінірек сызу үшін түбірдегі мәнді шығаруға болатын аталған түсірілген мән бар.

"sqrt\((? \d+)\)" - бұл тұрақты өрнекте бұл атау мән болып табылады.

формула виджеті

FormulaWidget.h

// Класс для отрисовки всех формул
class FormulaWidget : public QWidget
{
    Q_OBJECT
    using BaseClass = QWidget;
public:
    explicit FormulaWidget(QWidget* parent = nullptr);

public slots:
    // Слот для установки формулы
    void setFormula(const QString& formula);

protected:
    virtual void paintEvent(QPaintEvent* event) override;

private:
    QList<FormulaItem> m_items;
};

Сыныпта екі маңызды әдіс бар. Біріншісі формулаларды шығаратын жолды орнатуға арналған, ал екіншісі қайта анықталған әдіс paintEvent(). Қайта анықталған әдіс виджетті салуға жауап береді, біз ондағы барлық формулаларды да саламыз. . Бұл әдіс оқиғаны өңдеу әдістерінің стекінде Qt деп аталады. Бұл әдіс ешқашан тікелей шақырылмайды, белгілі бір оқиғалар орын алған кезде шақырылады, бірақ оны шақыру үшін update(). әдісін шақыру жеткілікті.

FormulaWidget.cpp

FormulaWidget::FormulaWidget(QWidget* parent) :
    BaseClass(parent)
{
    // Установим цвет фона виджета, по умолчанию он такой же, как в системном оформлении ОС
    QPalette pal = palette();
    pal.setColor(QPalette::Background, Qt::white);
    setAutoFillBackground(true);
    setPalette(pal);
}

void FormulaWidget::setFormula(const QString& formula)
{
    // Очищаем все формулы
    m_items.clear();

    // Создаём объект регулярного выражения для поиска формулы
    QRegularExpression sqrt_value(FormulaItem::REGULAR_EXPRESSION);
    // Ищем все вхождения формулы
    QRegularExpressionMatchIterator i = sqrt_value.globalMatch(formula);

    // создаём все объекты формул
    while (i.hasNext())
    {
        QRegularExpressionMatch match = i.next();
        if (match.hasMatch())
        {
            m_items.append(FormulaItem(match.captured("value")));
        }
    }

    // Запускаем перерисовку
    update();
}

void FormulaWidget::paintEvent(QPaintEvent* event)
{
    // Для перерисовки используется объект QPainter,
    // который обязательно должен получить объект за отрисовку которого он отвечает
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);
    p.setPen(Qt::black);

    QPoint formulaPos(2, 2);

    // Производим отрисовку всех формул, которые удалось найти
    for (const FormulaItem& item : m_items)
    {
        formulaPos = item.draw(formulaPos, p);
    }
}

Осы кодтың нәтижесінде мақаланың басындағы скриншотта көрсетілген қолданба алынады.

Мен сондай-ақ жоба кодын қосамын. Жүктеп алу

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз