10

I'm trying to do a small widget with a lineedit and a pushbutton. If the button is clicked, it should open a filedialog where I can select a file. The file name should then showed in the lineedit. Here is what i got so far:

#include "widget_openimage.h"
#include <QFontMetrics>

Widget_openimage::Widget_openimage(QWidget *parent) : QWidget(parent) {

// horizontal layout
layout = new QHBoxLayout();

// linedit on the left which shows the path of the chosen file
lineedit = new QLineEdit();
lineedit->setReadOnly(true);

// pushbutton on the right to select the file
btn = new QPushButton("...");
btn->setFixedSize(20,20);
connect(btn, SIGNAL(clicked()), this, SLOT(btn_clicked()));
connect(lineedit, SIGNAL(textChanged(QString)), this, SLOT(resize_to_content()));

layout->addWidget(lineedit);
layout->addWidget(btn);
this->setLayout(layout);
}

void Widget_openimage::btn_clicked() {
QString filename = QFileDialog::getOpenFileName(this,tr("Open"), "", tr("Image Files (*.png *.jpg *.bmp));
if (filename.isEmpty())
return;
else {
      lineedit->setText(filename);
     }
}

void Widget_openimage::resize_to_content() {
QString text = lineedit->text();
QFontMetrics fm = lineedit->fontMetrics();
int width = fm.boundingRect(text).width();
lineedit->resize(width, lineedit->height());
}

the openfile function of the button works fine, and the right path is shown in the lineedit too. however the resize doesnt work. can anyone lend me a hand?

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
yangsunny
  • 656
  • 5
  • 13
  • 32
  • How can the right path be shown it the lineedit, when you do not call it's `setText` method? Also you call `connect` to `textChanged(QString)` signal in the wrong place - you should call it in constructor. – Amartel May 04 '15 at 13:29
  • sorry, my fault, setText was of course in my original code, I only forgot it when I wrote the question. now I moved textChanged-connect into the constructor right after the other one. but it still doesnt work... – yangsunny May 04 '15 at 14:25

3 Answers3

10

First of all, there are some formatting issues with your code so i edited them and added some of my own. I used setFixedSize() instead of resize() because the user can decide to minimize the window and if that happens then why must you bother showing the full file path (I am guessing you want to show the full path at all times for a reason and not have the user being able to minimize the window to a point where not all the text in the lineedit shows.

Widget_openimage::Widget_openimage(QWidget *parent) : QWidget(parent) {

    // horizontal layout
    layout = new QHBoxLayout();

    // linedit on the left which shows the path of the chosen file
    lineedit = new QLineEdit;
    lineedit->setReadOnly(true);

    // pushbutton on the right to select the file
    btn = new QPushButton("...");
    btn->setFixedSize(20,20);

    connect(btn, SIGNAL(clicked()), this, SLOT(btn_clicked()));

    //do this connection so when the text in line edit is changed, its size    changes to show the full text
    connect(lineedit, SIGNAL(textChanged(QString)), this, SLOT(resize_to_content()));

    layout->addWidget(lineedit);
    layout->addWidget(btn);
    this->setLayout(layout);
}

void Widget_openimage::btn_clicked() {
    QString filename = QFileDialog::getOpenFileName(this,tr("Open"), "", tr("Image Files (*.png *.jpg *.bmp)"));

    //you have to set the file path text somewhere here
    lineedit->setText(filename);

    if (filename.isEmpty()) {
        return;
    }
}

void Widget_openimage::resize_to_content() {
    QString text = lineedit->text();

    //use QFontMetrics this way;
    QFont font("", 0);
    QFontMetrics fm(font);
    int pixelsWide = fm.width(text);
    int pixelsHigh = fm.height();

    lineedit->setFixedSize(pixelsWide, pixelsHigh);

    Widget_openimage::adjustSize();
}
  • thx for your answer, I just tried your methode. And when the path get longer, like from C:\image.jpg to D:\image\icon\icon.bmp, it works fine. But not the other way around. When I change the path with a long name to a short one. lineedit become centralized with space on the left and right side. – yangsunny May 04 '15 at 14:52
  • just add `Widget_openimage::adjustSize();` in the `resize_to_content()` function. I have updated my answer to reflect that. – Richardson Ansong May 04 '15 at 16:11
2

I do this way using proper font and changing only width:

void Widget_openimage::resizeToContent(QLineEdit *lineEdit)
{
    QString text = lineEdit->text();
    QFontMetrics fm(lineEdit->font());
    int pixelsWide = fm.width(text);
    lineEdit->setFixedWidth(pixelsWide);
    adjustSize();
}
Dmytro
  • 1,290
  • 17
  • 21
0

This works for Qt 6.3:

auto const edit = new QLineEdit;
connect(edit, &QLineEdit::textChanged, [edit](QString const& text){
    auto const text_size = edit->fontMetrics().size(0, text);
    auto const tm = edit->textMargins();
    auto const tm_size = QSize(tm.left() + tm.right(), tm.top() + tm.bottom());
    auto const cm = edit->contentsMargins();
    auto const cm_size = QSize(cm.left() + cm.right(), cm.top() + cm.bottom());
    auto const extra_size = QSize(8, 4); // hard coded stuff in Qt
    auto const contents_size = text_size + tm_size + cm_size + extra_size;

    QStyleOptionFrame op;
    op.initFrom(edit);
    auto const perfect_size =
        edit->style()->sizeFromContents(QStyle::CT_LineEdit, &op, contents_size);

    edit->setMinimumSize(perfect_size);
});

Replace setMinimumSize by setFixedSize if you also want to shrink the edit depending on its text.

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51