38

I'm trying to figure out how to make a horizontal line in Qt. This is easy to create in Designer but I want to create one programmatically. I've done some googleing and looked at the xml in a ui file but haven't been able to figure anything out.

This is what the xml from the ui file looks like:

  <widget class="Line" name="line">
   <property name="geometry">
    <rect>
     <x>150</x>
     <y>110</y>
     <width>118</width>
     <height>3</height>
    </rect>
   </property>
   <property name="orientation">
    <enum>Qt::Horizontal</enum>
   </property>
  </widget>
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
keegan3d
  • 10,357
  • 9
  • 53
  • 77

4 Answers4

45

A horizontal or vertical line is just a QFrame with some properties set. In C++, the code that is generated to create a line looks like this:

line = new QFrame(w);
line->setObjectName(QString::fromUtf8("line"));
line->setGeometry(QRect(320, 150, 118, 3));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
shoosh
  • 76,898
  • 55
  • 205
  • 325
  • 1
    Are `setGeometry` and `setFrameShadow` actually necessary? I'm still pretty new to Qt, but I would expect the style of frame shadow, by default, to depend on the overall Qt UI style. I'm trying to write cross-platform here. – Michael Scheper Jan 25 '16 at 01:13
  • 2
    @MichaelScheper no the only calls necessary are `setFrameShape()` and `setFrameShadow()`. – Michael Leonard Dec 09 '16 at 20:34
37

Here's another solution using PySide:

from PySide.QtGui import QFrame


class QHLine(QFrame):
    def __init__(self):
        super(QHLine, self).__init__()
        self.setFrameShape(QFrame.HLine)
        self.setFrameShadow(QFrame.Sunken)


class QVLine(QFrame):
    def __init__(self):
        super(QVLine, self).__init__()
        self.setFrameShape(QFrame.VLine)
        self.setFrameShadow(QFrame.Sunken)

Which can then be used as (for example):

from PySide.QtGui import QApplication, QWidget, QGridLayout, QLabel, QComboBox


if __name__ == "__main__":
    app = QApplication([])
    widget = QWidget()
    layout = QGridLayout()

    layout.addWidget(QLabel("Test 1"), 0, 0, 1, 1)
    layout.addWidget(QComboBox(), 0, 1, 1, 1)
    layout.addWidget(QHLine(), 1, 0, 1, 2)
    layout.addWidget(QLabel("Test 2"), 2, 0, 1, 1)
    layout.addWidget(QComboBox(), 2, 1, 1, 1)

    widget.setLayout(layout)
    widget.show()
    app.exec_()

Which results in the following:

Example of QHLine on Windows 10

Michael Leonard
  • 1,693
  • 20
  • 18
  • For future readers, PySide is only compatible with up to Python 3.6 or 3.6 Try installing PySide2,4,5,6 – ElSheikh Dec 06 '21 at 10:37
8

Here is a solution using standard PyQt5 that I derived from shoosh's answer:

from PyQt5 import QtWidgets

class QHSeparationLine(QtWidgets.QFrame):
  '''
  a horizontal separation line\n
  '''
  def __init__(self):
    super().__init__()
    self.setMinimumWidth(1)
    self.setFixedHeight(20)
    self.setFrameShape(QtWidgets.QFrame.HLine)
    self.setFrameShadow(QtWidgets.QFrame.Sunken)
    self.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
    return

class QVSeparationLine(QtWidgets.QFrame):
  '''
  a vertical separation line\n
  '''
  def __init__(self):
    super().__init__()
    self.setFixedWidth(20)
    self.setMinimumHeight(1)
    self.setFrameShape(QtWidgets.QFrame.VLine)
    self.setFrameShadow(QtWidgets.QFrame.Sunken)
    self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
    return

And if you want to add it (for example to a grid):

separator_vertical = separation_lines.QVSeparationLine()
separator_horizontal = separation_lines.QHSeparationLine()

grid = QtWidgets.QGridLayout()

grid.addWidget(your_widget_left_from_vertical_separator, 0, 0, 1, 1,)
grid.addWidget(separator_vertical, 0, 1, 1, 1)
grid.addWidget(your_widget_right_from_vertical_separator, 0, 2, 1, 1,)
grid.addWidget(separator_horizontal, 1, 0, 1, 2)
grid.addWidget(your_widget_below_horizontal_spacer, 2, 0, 1, 2)

Make sure to never use alignment on the separators, otherwise it will probably screw you over because they will not scale properly.

Just to show everything here is how to add it to your window:

import sys
if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    widget = QtWidgets.QWidget()
    widget.setLayout(grid)
    widget.show()
    sys.exit(app.exec())
tschmitz
  • 116
  • 4
2

You can use this

self.line = QFrame()
self.line.setGeometry(QRect(60, 110, 751, 20))
self.line.setFrameShape(QFrame.HLine)
self.line.setFrameShadow(QFrame.Sunken)

self.layout.addWidget(self.line)
  • 1
    It is the same as this answer: https://stackoverflow.com/a/41068447/6622587 and https://stackoverflow.com/a/61389578/6622587 – eyllanesc Oct 11 '21 at 22:29
  • you mean the one with c++? – Abdo Abdelaziz Oct 11 '21 at 23:48
  • I see that the 3 previous answers are translations of the same base answer(`QFrame.HLine` and `QFrame.Sunken`) but written in C ++, pyside and pyqt. What again does your answer bring? – eyllanesc Oct 11 '21 at 23:50
  • all of them they created class, and there are other people want simple solutions with python anyway i am not interested in c++ language and when i see posts about it i don't read them or understand them at all, and i didn't see yours please stop this kind of comment and let people learn we are not in class – Abdo Abdelaziz Oct 11 '21 at 23:54
  • IMO, I don't see anything new. For me it is a simple copy without contributing anything interesting so I gave my DV. For example, you could create a function that returns a QFrame with those attributes but it would still be a copy. The base is the same. – eyllanesc Oct 11 '21 at 23:55
  • the same i didn't see your post useful – Abdo Abdelaziz Oct 11 '21 at 23:56
  • You say: *the same i didn't see your post useful*, Give it a DV or raise a flag to have it removed. – eyllanesc Oct 11 '21 at 23:57
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – R. Marolahy Oct 12 '21 at 05:08