Results 1 to 8 of 8

Thread: Show/Hide height animation with SetFixedSize

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,368
    Thanks
    3
    Thanked 5,018 Times in 4,794 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Show/Hide height animation with SetFixedSize

    If you implement your own layout you are a master of allocating space for all the managed widgets. You can gradually (i.e. using a timer) increase the size hint returned by the layout to make your main widget grow and you can use setGeometry to manage where the child widgets go. You can also hide/show widgets as you see fit. Of course then you won't be able to show()/hide() those widgets directly or it would break your layout - you'd have to add appropriate API for that in your layout class.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  2. #2
    Join Date
    Feb 2008
    Posts
    491
    Thanks
    12
    Thanked 142 Times in 135 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11

    Talking Re: Show/Hide height animation with SetFixedSize

    Not sure if this is what you are after or not, but I got the animation to work using the "geometry" property.

    I couldn't get it to work using "height" either. Could it be because "height" is constant (int height () const), Wysota?
    Qt Code:
    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3.  
    4. from PyQt4.QtGui import *
    5. from PyQt4.QtCore import *
    6. import sys
    7.  
    8. connect = QObject.connect
    9.  
    10. app = QApplication(sys.argv)
    11.  
    12. def print_qsize(sz, title=""):
    13. print title, "W: ", sz.width(), " H: ", sz.height()
    14.  
    15. class ResizingWindow(QMainWindow):
    16. def __init__(self, parent=None):
    17. QMainWindow.__init__(self, parent)
    18. centralwidget = QWidget(self)
    19. self.setCentralWidget(centralwidget)
    20. layout = QVBoxLayout()
    21.  
    22.  
    23. checkbox1 = QCheckBox("Show First Widget", self)
    24. checkbox2 = QCheckBox("Show Second Widget", self)
    25. textedit1 = QPlainTextEdit(self)
    26. textedit2 = QPlainTextEdit(self)
    27.  
    28. layout.addWidget(checkbox1)
    29. layout.addWidget(textedit1)
    30. layout.addWidget(checkbox2)
    31. layout.addWidget(textedit2)
    32. centralwidget.setLayout(layout)
    33. connect(checkbox1, SIGNAL("toggled(bool)"), lambda b: self.hide_resize(textedit1, b))
    34. connect(checkbox2, SIGNAL("toggled(bool)"), lambda b: self.hide_resize(textedit2, b))
    35.  
    36. textedit1.hide()
    37. textedit2.hide()
    38.  
    39. self.layout().setSizeConstraint(QLayout.SetFixedSize)
    40.  
    41. def hide_resize(self, widget, show=True):
    42. if show:
    43. widget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) #got some flicker as the widget was growing without this
    44. widget.show()
    45. a = QPropertyAnimation(widget, "geometry", widget)
    46. a.setStartValue(QRect(widget.geometry().x(),widget.geometry().y(),0,0)) #use widget's original (x,y)
    47. a.setEndValue(QRect(widget.geometry().x(),widget.geometry().y(),256,192))
    48. a.setDuration(250)
    49. a.start()
    50. else:
    51. widget.hide()
    52.  
    53. mw = ResizingWindow()
    54. mw.show()
    55. app.exec_()
    To copy to clipboard, switch view to plain text mode 
    HTH
    Last edited by norobro; 20th September 2010 at 17:58. Reason: corrected code formatting

  3. #3
    Join Date
    Sep 2010
    Posts
    4
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Show/Hide height animation with SetFixedSize

    norobo: Your solution works fine, save for the problem that the resizing of the main window itself is not animated - which is also my goal.

    I have managed to come up with my own crappy layout implementation. It *works* and does everything i *want* it to, but there must be a better way

    a sample run gives me:
    Qt Code:
    1. increment is 0.5
    2. increment is 0.5
    3. show, going for height 125
    4. got begin 0 end 125 step 0.5
    5. amount_grown is 124
    6. hides
    7. amount_shrunk is 0
    8. show, going for height 125
    9. got begin 0 end 125 step 0.5
    10. amount_grown is 124
    11. hides
    12. amount_shrunk is 0
    13. show, going for height 125
    14. got begin 0 end 125 step 0.5
    15. amount_grown is 124
    16. show, going for height 125
    17. got begin 0 end 125 step 0.5
    18. amount_grown is 124
    19. hides
    20. amount_shrunk is 0
    21. show, going for height 125
    22. got begin 0 end 125 step 0.5
    23. amount_grown is 124
    24. hides
    25. amount_shrunk is 0
    26. show, going for height 125
    27. got begin 0 end 125 step 0.5
    28. amount_grown is 124
    29.  
    30. real 0m13.645s
    31. user 0m2.369s
    32. sys 0m1.193s
    To copy to clipboard, switch view to plain text mode 

    -- way too much CPU time for this

    The updated code is:
    Qt Code:
    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3.  
    4. from PyQt4.QtGui import *
    5. from PyQt4.QtCore import *
    6. import sys
    7.  
    8. connect = QObject.connect
    9.  
    10. app = QApplication(sys.argv)
    11.  
    12. def copy_size(size):
    13. return QSize(size.width(), size.height())
    14.  
    15. def xfloat_range(begin,end,step):
    16. print "got begin", begin, "end", end, "step", step
    17. while begin < end:
    18. yield begin
    19. begin += step
    20.  
    21. def xfloat_range_decrement(begin, end, step):
    22. while begin > end and begin > 0:
    23. yield begin
    24. begin -= step
    25.  
    26.  
    27. def print_qsize(sz, title=""):
    28. print title, "W: ", sz.width(), " H: ", sz.height()
    29.  
    30. class AnimatedLayout(QHBoxLayout):
    31. def __init__(self, child, size, parent = None):
    32. QHBoxLayout.__init__(self, parent)
    33. self._name = ""
    34.  
    35. child.sizeHint = lambda: QSize()
    36. child.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Ignored)
    37.  
    38. self.child = child
    39. self.addWidget(child)
    40. self.mandated_size = QSize(size.height(), 0)
    41. self.preferred_size = size
    42.  
    43. self.setContentsMargins(0,0,0,0)
    44. self.setSpacing(0)
    45.  
    46. self.duration = 250
    47.  
    48. self.amount_grown = 0
    49. self.amount_shrunk = 0
    50. self.generator = None
    51.  
    52. self.timer = QTimer(self)
    53. self.child.setVisible(True)
    54.  
    55. self.show = self.startShow
    56. self.hide = self.startHide
    57. self.child.show = self.show
    58. self.child.hide = self.hide
    59.  
    60. print "increment is ", self.increment
    61.  
    62. @property
    63. def increment(self):
    64. return float(float(self.preferred_size.height())/float(self.duration))
    65.  
    66. def setGeometry(self, rect):
    67. #print_qsize(rect.size(), self._name)
    68. super(type(self), self).setGeometry(rect)
    69.  
    70. def sizeHint(self):
    71. return self.mandated_size
    72.  
    73. def setAnimationDuration(self, msecs):
    74. self.duration = msecs
    75.  
    76. def timer_fire_show(self):
    77. if not self.generator:
    78. raise Exception("Generator not initialized!")
    79. try:
    80. h = int(self.generator.next())
    81. #print h
    82. if h > self.amount_grown:
    83. self.mandated_size.setHeight(h)
    84. self.amount_grown = h
    85. self.update()
    86. except StopIteration:
    87. #finished:
    88. print "amount_grown is", self.amount_grown
    89. self.timer.stop()
    90. #do any cleanup, just a final check
    91. self.mandated_size = copy_size(self.preferred_size)
    92. self.update()
    93. QObject.disconnect(self.timer, SIGNAL("timeout()"), self.timer_fire_show)
    94. del self.generator
    95.  
    96. def startShow(self):
    97. print "show, going for height", self.preferred_size.height()
    98. #start an animation here using a timer that will update both our sizeHint
    99. #as well as the widget's size accordingly
    100. self.generator = xfloat_range(0, self.preferred_size.height(), self.increment)
    101. QObject.connect(self.timer, SIGNAL("timeout()"), self.timer_fire_show)
    102. self.amount_grown = 0
    103. self.timer.start(1)
    104.  
    105. def timer_fire_hide(self):
    106. if not self.generator:
    107. raise Exception("Generator not initialized")
    108. try:
    109. h = int(self.generator.next())
    110. #print h
    111. if h < self.amount_shrunk:
    112. self.mandated_size.setHeight(h)
    113. self.amount_shrunk = h
    114. self.update()
    115. except StopIteration:
    116. print "amount_shrunk is", self.amount_shrunk
    117. self.timer.stop()
    118. self.mandated_size.setHeight(0)
    119. self.update()
    120. QObject.disconnect(self.timer, SIGNAL("timeout()"), self.timer_fire_hide)
    121.  
    122. def startHide(self):
    123. print "hides"
    124. self.generator = xfloat_range_decrement(self.preferred_size.height(), 0, self.increment)
    125. QObject.connect(self.timer, SIGNAL("timeout()"), self.timer_fire_hide)
    126. self.amount_shrunk = self.preferred_size.height()
    127. self.timer.start(1)
    128.  
    129. def setVisible(self, b):
    130. "convenience method"
    131. if b:
    132. self.startShow()
    133. else:
    134. self.startHide()
    135.  
    136. class ResizingWindow(QMainWindow):
    137. def __init__(self, parent=None):
    138. QMainWindow.__init__(self, parent)
    139. self.layout().setSizeConstraint(QLayout.SetFixedSize)
    140.  
    141. centralwidget = QWidget(self)
    142. self.setCentralWidget(centralwidget)
    143. layout = QVBoxLayout()
    144.  
    145.  
    146. checkbox1 = QCheckBox("Show First Widget", self)
    147. checkbox2 = QCheckBox("Show Second Widget", self)
    148. textedit1 = QPlainTextEdit(self)
    149. textedit2 = QPlainTextEdit(self)
    150.  
    151. anim_wrapper1 = AnimatedLayout(textedit1, QSize(150, 125))
    152. anim_wrapper1._name = "anim_wrapper1"
    153. self.anim_wrapper1 = anim_wrapper1
    154. anim_wrapper2 = AnimatedLayout(textedit2, QSize(150, 125))
    155. anim_wrapper2._name = "anim_wrapper2"
    156. self.anim_wrapper2 = anim_wrapper2
    157.  
    158.  
    159. layout.addWidget(checkbox1)
    160. layout.addLayout(anim_wrapper1)
    161. layout.addWidget(checkbox2)
    162. layout.addLayout(anim_wrapper2)
    163. centralwidget.setLayout(layout)
    164.  
    165. connect(checkbox1, SIGNAL("toggled(bool)"), anim_wrapper1.setVisible)
    166. connect(checkbox2, SIGNAL("toggled(bool)"), anim_wrapper2.setVisible)
    167. mw = ResizingWindow()
    168. mw.show()
    169. app.exec_()
    To copy to clipboard, switch view to plain text mode 
    Last edited by mnunberg; 21st September 2010 at 01:55. Reason: updated contents

  4. #4
    Join Date
    Sep 2010
    Posts
    4
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Show/Hide height animation with SetFixedSize

    Well, I've reworked a cleaner example, but this one jitters, and it doesn't seem to work in my actual code -- I get the children widgets in their own windows?:

    Qt Code:
    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3.  
    4. from PyQt4.QtGui import *
    5. from PyQt4.QtCore import *
    6. import sys
    7.  
    8. connect = QObject.connect
    9.  
    10. app = QApplication(sys.argv)
    11.  
    12. def print_qsize(sz, title=""):
    13. print title, "W: ", sz.width(), " H: ", sz.height()
    14.  
    15. class AnimatedLayout(QLayout):
    16. STATE_HIDDEN, STATE_VISIBLE, STATE_ANIMATING = range(3)
    17.  
    18. def __init__(self, child, size, parent = None):
    19. super(type(self),self).__init__(parent)
    20. self._name = ""
    21.  
    22. child.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
    23. #self.setSizeConstraint(QLayout.SetFixedSize)
    24.  
    25. self.child = child
    26. self.mandated_size = QSize(size.width(), 0)
    27. self.preferred_size = size
    28.  
    29. self.setContentsMargins(0,0,0,0)
    30. self.setSpacing(0)
    31.  
    32. self.duration = 250
    33. self.child.setVisible(True)
    34.  
    35. self.show = self.startShow
    36. self.hide = self.startHide
    37. self.child.show = self.show
    38. self.child.hide = self.hide
    39. self.child.setVisible = self.setVisible
    40.  
    41. self.child_state = self.STATE_VISIBLE
    42.  
    43. #these two segfaulted if i tried to do anything legit with them?
    44. def count(self):
    45. return 0
    46. def itemAt(self, index):
    47. return None
    48.  
    49. def setGeometry(self, rect):
    50. if not self.child_state in (self.STATE_ANIMATING, self.STATE_VISIBLE):
    51. return
    52. #super(type(self), self).setGeometry(rect)
    53. self.child.setGeometry(rect)
    54.  
    55. def sizeHint(self):
    56. return self.mandated_size
    57. #return self.child.sizeHint()
    58.  
    59. def setAnimationDuration(self, msecs):
    60. self.duration = msecs
    61.  
    62. def startShow(self):
    63. self._start_animation(True)
    64. def startHide(self):
    65. self._start_animation(False)
    66.  
    67. def _start_animation(self, show=True):
    68. a = QPropertyAnimation(self.child, "geometry", self)
    69. g = self.child.geometry()
    70. g.setHeight(0)
    71. a.setStartValue(g)
    72. g.setHeight(self.preferred_size.height())
    73. a.setEndValue(g)
    74. a.setEasingCurve(QEasingCurve.OutQuad)
    75. a.setDuration(self.duration)
    76. def valueChanged(qv):
    77. r = qv.toRect()
    78. self.mandated_size.setHeight(r.height())
    79. self.update()
    80. connect(a, SIGNAL("valueChanged(QVariant)"), valueChanged)
    81.  
    82. if not show:
    83. a.setDirection(a.Backward)
    84. connect(a, SIGNAL("finished()"), lambda: setattr(self, "child_state", self.STATE_HIDDEN))
    85. else:
    86. a.setDirection(a.Forward)
    87. connect(a, SIGNAL("finished()"), lambda: setattr(self, "child_state", self.STATE_VISIBLE))
    88. a.start(a.DeleteWhenStopped)
    89.  
    90.  
    91. def setVisible(self, b):
    92. "convenience method"
    93. if b:
    94. self.startShow()
    95. else:
    96. self.startHide()
    97.  
    98. class ResizingWindow(QMainWindow):
    99. def __init__(self, parent=None):
    100. QMainWindow.__init__(self, parent)
    101. self.layout().setSizeConstraint(QLayout.SetFixedSize)
    102.  
    103. centralwidget = QWidget(self)
    104. self.setCentralWidget(centralwidget)
    105. layout = QVBoxLayout()
    106.  
    107.  
    108. checkbox1 = QCheckBox("Show First Widget", self)
    109. checkbox2 = QCheckBox("Show Second Widget", self)
    110. textedit1 = QPlainTextEdit(self)
    111. textedit2 = QPlainTextEdit(self)
    112. textedit1.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
    113. textedit2.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
    114.  
    115. anim_wrapper1 = AnimatedLayout(textedit1, QSize(150, 125))
    116. anim_wrapper1._name = "anim_wrapper1"
    117. self.anim_wrapper1 = anim_wrapper1
    118. anim_wrapper2 = AnimatedLayout(textedit2, QSize(150, 125))
    119. anim_wrapper2._name = "anim_wrapper2"
    120. self.anim_wrapper2 = anim_wrapper2
    121.  
    122.  
    123. layout.addWidget(checkbox1)
    124. layout.addLayout(anim_wrapper1)
    125. layout.addWidget(checkbox2)
    126. layout.addLayout(anim_wrapper2)
    127. centralwidget.setLayout(layout)
    128.  
    129. connect(checkbox1, SIGNAL("toggled(bool)"), anim_wrapper1.setVisible)
    130. connect(checkbox2, SIGNAL("toggled(bool)"), anim_wrapper2.setVisible)
    131. mw = ResizingWindow()
    132. mw.show()
    133. app.exec_()
    To copy to clipboard, switch view to plain text mode 
    Last edited by mnunberg; 21st September 2010 at 04:41. Reason: updated contents

  5. #5
    Join Date
    Apr 2009
    Posts
    3
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Show/Hide height animation with SetFixedSize

    I have same kind of problem and would like to resize window when i hide a widget from layout(so this will give user dock kind of experience), this can be easily done by setting layout property QLayout::setSizeConstraint(QLayout::SetFixedSize), but then i can't resize window.

    so is there any way where i can re size window without loosing dock kind of effect when i hide or show child widget from layout.

    Please note that i don't want to implement re size event handling.
    thanks.
    Last edited by junky; 24th November 2010 at 11:22.

Similar Threads

  1. how to show an app if it manually hide
    By jthacker in forum Qt Programming
    Replies: 1
    Last Post: 26th March 2010, 13:02
  2. how to show and hide frames?
    By rambo83 in forum Qt Programming
    Replies: 2
    Last Post: 6th January 2010, 09:53
  3. Hide and Show QMenu
    By febil in forum Qt Programming
    Replies: 3
    Last Post: 25th March 2009, 09:31
  4. hide from taskbar but show to ALT-TAB
    By musikit in forum Qt Programming
    Replies: 0
    Last Post: 15th August 2008, 16:14
  5. Show or hide a form
    By Gayathri in forum Newbie
    Replies: 11
    Last Post: 17th November 2006, 12:39

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.