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 хостинг.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
OI
  • Ora Iro
  • Жел. 24, 2024, 6:38 Т.Ж.

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

  • Нәтиже:40ұпай,
  • Бағалау ұпайлары-8
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:50ұпай,
  • Бағалау ұпайлары-4
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
Соңғы пікірлер
ИМ
Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectМаусым 4, 2022, 3:49 Т.Ж.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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