Как получить смещение текста QLineEdit, когда QAction находится на лидирующей позиции

Если вы используете поиск Eclipse, вы можете включить опцию «DOTALL», чтобы сделать «.». сопоставить любой символ, включая разделители строк: просто добавьте «(? s)» в начале строки поиска. Пример:

(?s).*<FooBar>
2
задан Thibaut B. 16 January 2019 в 09:15
поделиться

1 ответ

Я должен признать, что (до прочтения вопроса ОП) я не знал о QLineEdit::addAction() . Таким образом, я написал небольшой пример testQLineEditAction.cc:

#include <QtWidgets>

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // init GUI
  QLineEdit qEdit;
  qEdit.addAction(QIcon("./document-properties.svg"), QLineEdit::LeadingPosition);
  qEdit.addAction(QIcon("./document-save.svg"), QLineEdit::TrailingPosition);
  qEdit.show();
  // runtime loop
  return app.exec();
}

и вот как это выглядит (скомпилировано в cygwin64 ):

Snapshot of testQLineEditAction

После этого я немного покопался в woboq.org , чтобы узнать, как это реализовано.

Я начал в QLineEdit::paintEvent() :

void QLineEdit::paintEvent(QPaintEvent *)
{

...

  QStyleOptionFrame panel;
  initStyleOption(&panel);

...

  QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
  r.setX(r.x() + d->effectiveLeftTextMargin());
  r.setY(r.y() + d->topTextMargin);
  r.setRight(r.right() - d->effectiveRightTextMargin());
  r.setBottom(r.bottom() - d->bottomTextMargin);

Это интересно: прямоугольник для содержания извлекается и затем исправляется внутренними смещениями.

  QFontMetrics fm = fontMetrics();

...

  QRect lineRect(r.x() + d->horizontalMargin, d->vscroll, r.width() - 2*d->horizontalMargin, fm.height());

Насчет d->horizontalMargin, я не совсем уверен, но пока проигнорировал его и следовал вместо него d->effectiveLeftTextMargin() :

int QLineEditPrivate::effectiveLeftTextMargin() const
{
    return effectiveTextMargin(leftTextMargin, leftSideWidgetList(), sideWidgetParameters());
}

... [ 1149]

static int effectiveTextMargin(int defaultMargin, const QLineEditPrivate::SideWidgetEntryList &widgets,
                               const QLineEditPrivate::SideWidgetParameters &parameters)
{
    if (widgets.empty())
        return defaultMargin;
    return defaultMargin + (parameters.margin + parameters.widgetWidth) *
           int(std::count_if(widgets.begin(), widgets.end(),
                             [](const QLineEditPrivate::SideWidgetEntry &e) {
                                 return e.widget->isVisibleTo(e.widget->parentWidget()); }));
}

Итак, я пришел к выводу, что QLineEditPrivate::effectiveLeftTextMargin() рассматривает пространство для значков действий, когда определяется эффективный размер текстового прямоугольника.

Жаль, что все эти функции private и поэтому недоступны извне. Подумав некоторое время, как получить к ним доступ извне и изучив документацию. если я что-то не наблюдал, у меня появилась идея использовать QAction непосредственно для этого:

#include <QtWidgets>

void inspect(const QString &cmd, QAction &qCmd)
{
  qDebug() << (cmd + "->associatedWidgets().size():")
    << qCmd.associatedWidgets().size();
  int i = 0;
  for (QWidget *const pQWidget : qCmd.associatedWidgets()) {
    qDebug() << '[' << i++ << "]:"
      << typeid(*pQWidget).name()
      << "geometry:" << pQWidget->geometry();
  }
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // init GUI
  QLineEdit qEdit;
  qEdit.setText("012345678901234567890123456789");
  QAction *const pQCmd1
    = qEdit.addAction(QIcon("./document-properties.svg"), QLineEdit::LeadingPosition);
  QAction *const pQCmd2
    = qEdit.addAction(QIcon("./document-save.svg"), QLineEdit::TrailingPosition);
  qEdit.show();
  qDebug() << "qEdit.geometry():" << qEdit.geometry();
  inspect("pQCmd1", *pQCmd1);
  inspect("pQCmd2", *pQCmd2);
  // runtime loop
  return app.exec();
}

Вывод на консоль:

Qt Version: 5.9.4
qEdit.geometry(): QRect(0,0 200x23)
"pQCmd1->associatedWidgets().size():" 2
[ 0 ]: 9QLineEdit geometry: QRect(0,0 200x23)
[ 1 ]: 19QLineEditIconButton geometry: QRect(4,2 22x18)
"pQCmd2->associatedWidgets().size():" 2
[ 0 ]: 9QLineEdit geometry: QRect(0,0 200x23)
[ 1 ]: 19QLineEditIconButton geometry: QRect(174,2 22x18)

Для сравнения значений, другой снимок с измененными значками (рамка, нарисованная в SVG для отображения размера значков), которая была увеличена (коэффициент 5):

Magnified Snapshot of testQLineEditAction (factor 5)

[1154]

Слева [1120 ] сообщаемое положение (4, 2), но левая рамка значка находится в 8 пикселях от левой границы QLineEdit. Безусловно, вокруг QLineEditIconButton есть рамка, которую также необходимо учитывать (и я не исследовал, как ее найти). Ширина кадра может быть предметом стиля движка и, таким образом, варьироваться между платформами. Чтобы сделать такую ​​попытку надежной и переносимой, соответствующие значения должны быть получены из виджетов или из стиля. Это начинает становиться утомительным занятием с большим или меньшим шансом на успех.

Однажды я попал в похожую ситуацию, пытаясь ответить . SO: Как автоматически увеличивать / уменьшать размер текста в метке в Qt .


Относительно QLineEdit::cursorRect() :

Я считаю, что использование QLineEdit::cursorRect() (также) в лучшем случае хрупко.

Я изменил свой приведенный выше пример, чтобы проверить это:

#include <QtWidgets>

class LineEdit: public QLineEdit {

  public:
    QRect cursorRect() const { return QLineEdit::cursorRect(); }
};

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // init GUI
  LineEdit qEdit;
  qEdit.setText("012345678901234567890123456789");
  qEdit.addAction(QIcon("./document-properties.svg"), QLineEdit::LeadingPosition);
  qEdit.addAction(QIcon("./document-save.svg"), QLineEdit::TrailingPosition);
  qEdit.show();
  qDebug() << "qEdit.cursorRect():" << qEdit.cursorRect();
  // runtime loop
  return app.exec();
}

Вывод на консоль:

Qt Version: 5.9.4
qEdit.geometry(): QRect(0,0 200x23)
qEdit.cursorRect(): QRect(253,0 9x16)

Забавно, что позиция х курсора не только достаточно высока & ndash; это даже выше, чем ширина qEdit. Как идет? Исходный текст "012345678901234567890123456789", который я вставил в qEdit, приводит к тому, что курсор оказывается ближе к праву, в результате чего происходит горизонтальная прокрутка. Положение курсора, по-видимому, связано с шириной виртуального текста (включая обрезанный диапазон с левой стороны).

0
ответ дан Scheff 16 January 2019 в 09:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: