2016-05-23 12 views
0

私は上部にバナーが必要なPyQt5アプリケーションで作業しています。バナーは、幅が常にウィンドウの幅で、高さが一定の割合でなければならない、ワイドイメージです。つまり、バナー画像の高さはウィンドウの幅に依存するはずです。バナーの下にあるウィジェット(メインコンテンツ)は、使用可能なすべての垂直スペースを埋めるために伸ばす必要があります。ウィジェットの高さをその幅に固定された比率にする方法

私は基本的にPyQt5にthis SO answerを移植しました:(。この例では、私はthis無料のバナー画像を使用していますが、それについては何も特別なことはありません)

class Banner(QWidget): 

    def __init__(self, parent): 
     super(Banner, self).__init__(parent) 

     self.setContentsMargins(0, 0, 0, 0) 

     pixmap = QPixmap('banner-1071797_960_720.jpg') # see note below 

     self._label = QLabel(self) 
     self._label.setPixmap(pixmap) 
     self._label.setScaledContents(True) 
     self._label.setFixedSize(0, 0) 
     self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) 

     self._resizeImage() 

    def resizeEvent(self, event): 
     super(Banner, self).resizeEvent(event) 
     self._resizeImage() 

    def _resizeImage(self): 
     pixSize = self._label.pixmap().size() 
     pixSize.scale(self.size(), Qt.KeepAspectRatio) 
     self._label.setFixedSize(pixSize) 

私が置かれていますラベルは、メインコンテンツのプレースホルダとして機能する以下のアプリケーションコードでバナー:

if __name__ == '__main__': 

    app = QApplication(sys.argv) 

    widget = QWidget() 
    widget.setContentsMargins(0, 0, 0, 0) 
    layout = QVBoxLayout(widget) 

    banner = Banner(widget) 
    bannerSizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) 
    bannerSizePolicy.setHeightForWidth(True) 
    banner.setSizePolicy(bannerSizePolicy) 
    layout.addWidget(banner) 

    label = QLabel('There should be a banner above') 
    label.setStyleSheet('QLabel { background-color: grey; color: white; }'); 
    layout.addWidget(label) 
    layout.setStretch(0, 1) 

    widget.resize(320, 200) 
    widget.move(320, 200) 
    widget.setWindowTitle('Banner Tester') 
    widget.show() 

    sys.exit(app.exec_()) 

問題は、ラベルの100%を満たす、ありますwindow - バナーはまったく表示されません。

私はさまざまなサイズのポリシーとストレッチファクタを試し、サイズポリシーを完全に削除しましたが、私が必要とする方法を見つけられませんでした。バナー内のイメージは、ウィンドウの幅に合わせて比例してスケーリングされ、ラベルはウィンドウ内の残りの垂直スペースを埋める必要があります。

アイデア?

+1

ウィジェットの実装が不完全であるため、レイアウトで正しく機能しません。 'hasHeightForWidth'を正しく実装する必要があります。例えば、 [この回答](http://stackoverflow.com/a/18923122/1329652)。 –

答えて

0

@ kuba-oberさんのコメントは正しくありました:私はhasHeightForWidth()heightForWidth()をバナークラスに実装しなければなりませんでした。

ここでは、私が望むように動作する変更されたコードです。すべての変更にはコード内にコメントがあります。

class Banner(QWidget): 

    def __init__(self, parent): 
     super(Banner, self).__init__(parent) 

     self.setContentsMargins(0, 0, 0, 0) 

     pixmap = QPixmap('banner-1071797_960_720.jpg') 

     # First, we note the correct proportion for the pixmap 
     pixmapSize = pixmap.size() 
     self._heightForWidthFactor = 1.0 * pixmapSize.height()/pixmapSize.width() 

     self._label = QLabel('pixmap', self) 
     self._label.setPixmap(pixmap) 
     self._label.setScaledContents(True) 
     self._label.setFixedSize(0, 0) 
     self._label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) 

     self._resizeImage(self.size()) 

    def hasHeightForWidth(self): 
     # This tells the layout manager that the banner's height does depend on its width 
     return True 

    def heightForWidth(self, width): 
     # This tells the layout manager what the preferred and minimum height are, for a given width 
     return math.ceil(width * self._heightForWidthFactor) 

    def resizeEvent(self, event): 
     super(Banner, self).resizeEvent(event) 
     # For efficiency, we pass the size from the event to _resizeImage() 
     self._resizeImage(event.size()) 

    def _resizeImage(self, size): 
     # Since we're keeping _heightForWidthFactor, we can code a more efficient implementation of this, too 
     width = size.width() 
     height = self.heightForWidth(width) 
     self._label.setFixedSize(width, height) 

if __name__ == '__main__': 

    app = QApplication(sys.argv) 

    widget = QWidget() 
    widget.setContentsMargins(0, 0, 0, 0) 
    layout = QVBoxLayout(widget) 

    banner = Banner(widget) 
    # Turns out we don't need the bannerSizePolicy now 
# bannerSizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) 
# bannerSizePolicy.setHeightForWidth(True) 
# banner.setSizePolicy(bannerSizePolicy) 
    layout.addWidget(banner) 

    label = QLabel('There should be a banner above') 
    label.setStyleSheet("QLabel { background-color: grey; color: white; }"); 
    layout.addWidget(label) 
    layout.setStretch(1, 1) 

    widget.resize(320, 200) 
    widget.move(320, 200) 
    widget.setWindowTitle('Banner Tester') 
    widget.show() 

    sys.exit(app.exec_()) 
関連する問題