Skip to content

Allow turtledemo code pane to get wider. #65796

Closed

Description

@terryjreedy
BPO 21597
Nosy @terryjreedy, @ned-deily
Files
  • turtledemo_pane.patch
  • turtledemo_pane.patch
  • tkinter_tear.mov
  • turtledemo_grid.patch
  • turtledemo_pane_srcoll_fix.patch
  • turtledemo_pane_srcoll_fix.patch
  • turtledemo_pane_scroll_FLAT.patch
  • turtledemo_pane_scroll_SOLID.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/terryjreedy'
    closed_at = <Date 2014-07-23.19:07:27.150>
    created_at = <Date 2014-05-28.19:53:07.714>
    labels = ['type-bug']
    title = 'Allow turtledemo code pane to get wider.'
    updated_at = <Date 2014-07-23.22:06:48.865>
    user = 'https://github.com/terryjreedy'

    bugs.python.org fields:

    activity = <Date 2014-07-23.22:06:48.865>
    actor = 'Lita.Cho'
    assignee = 'terry.reedy'
    closed = True
    closed_date = <Date 2014-07-23.19:07:27.150>
    closer = 'terry.reedy'
    components = []
    creation = <Date 2014-05-28.19:53:07.714>
    creator = 'terry.reedy'
    dependencies = []
    files = ['35503', '35546', '35859', '35874', '35877', '35878', '35889', '35890']
    hgrepos = []
    issue_num = 21597
    keywords = ['patch']
    message_count = 46.0
    messages = ['219296', '219539', '219543', '219902', '219920', '220120', '220122', '221146', '221147', '221206', '222301', '222302', '222306', '222317', '222318', '222319', '222320', '222321', '222322', '222323', '222326', '222327', '222328', '222330', '222331', '222332', '222398', '222411', '222420', '222423', '222425', '222434', '222435', '222441', '222490', '222491', '223595', '223627', '223718', '223719', '223731', '223760', '223763', '223773', '223786', '223787']
    nosy_count = 5.0
    nosy_names = ['terry.reedy', 'ned.deily', 'jesstess', 'python-dev', 'Lita.Cho']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue21597'
    versions = ['Python 2.7', 'Python 3.4', 'Python 3.5']

    Activity

    1. terryjreedy commented on May 28, 2014

      @terryjreedy
      MemberAuthor

      Turtledemo (python -m turtledemo) has a text pane for code and a canvas pane for the actual demo. The code pane is fixed at about 60% of the width needed to display full-width code lines. If the window is expanded horizontally, all the expansion goes to the canvas pane, where it is mostly not needed or used. Almost all the examples are a fixed size on the canvas, independent of the size of the window on the canvas.

      Having the text pane too narrow makes it harder to read and copy the code than it would be if entire code lines were visible. The default width of the overall window is about 1250 pixels on my big monitor. Many people have more pixels than that. Even on smaller screen, people might like to temporarily allocate more space to the text. So I think the best solution, if possible with tkinter, would be a movable divider.

    2. LitaCho commented on Jun 2, 2014

      LitaChomannequin
      Mannequin

      I'll take this on.

    3. terryjreedy commented on Jun 2, 2014

      @terryjreedy
      MemberAuthor

      The patch for bpo-18132 replaced pack with grid, But the replacement seemed partial even within the top frame (but I may have misread). Mixing the two is known to be a bad idea. http://effbot.org/tkinterbook/grid.htm has a big warning box about this. I think we can fix both issues with a 2row x 4col grid. The first col would have a minsize as now but be expandable. The canvas would have a rowspan of 3. The bottom row would have a fixed size so it does not disappear. I don't know if gridding a frame with a widget and scrollbars packed inside is ok or not. If not, it should be possible to grid widget and scrollbars instead. In any case, the result should be a bit simpler, with at least 1 less intermediate frame (for the 3 buttons under the canvas. Unless someone else would rather, I will do a final review, test, and commit.

      If you try an approach that does not work, say so and I will know not to suggest it ;-).

    4. self-assigned this
      on Jun 2, 2014
    5. LitaCho commented on Jun 6, 2014

      LitaChomannequin
      Mannequin

      Hi Terry!

      I went ahead and added a movable divider (also known as a "sash") using the PanedWindow widget. http://effbot.org/tkinterbook/panedwindow.htm#reference

      I also converted the master window to use a grid geometry manager. It looks like you can use pack manager and grid managers together as long as each manager is separated by a container/frame. So I use the pack manager to manage the scrollbars within the Frame. It ended up working out nicely.

      I've attached a patch and would like to submit it for review!

    6. terryjreedy commented on Jun 7, 2014

      @terryjreedy
      MemberAuthor

      I ran the patched code but have not looked at the code itself. Pending such a look, I would consider committing it if we cannot do better, as it solves both issues. However, there are two visual issues.

      1. The minor one: The blue label does not have drop shadows, the red/yellow buttons do. I suspect the intent is to differentiate something that cannot be pressed from things that can. But the effect at the boundary is bit jarring. On the bottem, the buttons are underlined in black, the label not. On the top, the button have a very light shading that makes them look narrower than they are. I wonder if it would look better if the label has shadows to match, or if there were a small separation between the labels and buttons (horizonatal padding on the label?). If you understand what is bother me, see if you can come up with something that looks better than you. Even post a couple of alternatives, if you want.

      2. More important: when I move the slider right, the text widen and the canvas narrows relatively smoothly. When I go the other way, to the left, a trail of vertical line is left behind for perhaps a third of a second. The right scrollbar, the vertical canvas bars, jiggles back and forth about a few mm, as if it were not fixed in place but attached to springs and dragged by the canvas. This happens even with both panes empty. It looks pretty bad.

      I wonder if this has anything to do with mixing grid and pack. An experiment would be to put an empty PanedWindow into a window and see if it behaves as badly. I have a decent system, and moving -> work almost ok, so something seems wrong.

    7. LitaCho commented on Jun 9, 2014

      LitaChomannequin
      Mannequin

      Hi Terry!

      1. More important: when I move the slider right, the text widen and the canvas narrows relatively smoothly.

      This is not due to the mixing of Pack and Grid Managers. This is due to adding Frames within a Pane Window. If I just create two empty Pane Windows, I don't get the lag. However, if I add a Frame container within Pane Window, I do. I've tried switching between using only the Pack Manager and then again using only the Grid Manager. However, that lag still exists.

      I have the code here if you want to try the packed version.

      from tkinter import *
      root = Tk()
      m = PanedWindow(root, orient=HORIZONTAL, sashwidth=10)
      rightF =  Frame(m)
      leftF = Frame(m)
      top = Label(leftF, text="lefgt pane", bg='blue')
      bottom = Label(rightF, text="right pane", bg='red')
      top.pack(fill=BOTH, expand=1)
      bottom.pack(fill=BOTH, expand=1)
      m.add(leftF)
      m.add(rightF)
      
      m.pack(fill=BOTH, expand=1)
      mainloop()
      
    8. LitaCho commented on Jun 9, 2014

      LitaChomannequin
      Mannequin
      1. The minor one: The blue label does not have drop shadows, the red/yellow buttons do.

      I created a patch to add a border around the label and create some padding between the buttons and the label. Let me know if this is less jarring than the previous version.

    9. LitaCho commented on Jun 21, 2014

      LitaChomannequin
      Mannequin

      ping!

      I just want to know how I should proceed with this ticket. I can try removing the Frames with get rid of the lag, but then I feel like we can't use the Grid Manager at all. :\

    10. terryjreedy commented on Jun 21, 2014

      @terryjreedy
      MemberAuthor

      I downloaded new patch and will try to look at it this weekend.

    11. terryjreedy commented on Jun 21, 2014

      @terryjreedy
      MemberAuthor

      I played around for a couple of hours, but am not sure what I want to do other than catching currently uncaught turtle.Terminator (in another issue). I might want to try my original idea of just using grid, without PanedWindow.

      Another idea is to ttk widgets, including PanedWindow, to see if they act the same.
      http://www.tkdocs.com/tutorial/complex.html
      says "Typically the widgets you're adding to a panedwindow will be frames containing many other widgets.". Than implies that the combination should work. The (partial) example there (including a Python tkinter version) uses two ttk.LabelFrames in a ttk.PanedWindow. Perhaps you can try your minimal example with a ttk Frame.

      Through Google I found an example of PanedWindow with two Frames here (line 29):
      http://nullege.com/codes/show/src%40r%40o%40robotframework-workbench-0.5%40rwb%40editor%40custom_notebook.py/29/Tkinter.PanedWindow/python
      so it is definitely being done. If we cannot get it to work without tearing, I may ask on StackOverflow. So please post your minimal code of empty frames that exhibits the problem.

    12. LitaCho commented on Jul 4, 2014

      LitaChomannequin
      Mannequin

      Hi Terry, I started digging into this deeper and it looks like my tests doesn't tear in Python 2.7. I have tried on Python 3.5 and 3.4 and it tears on those versions.

      I also tried the ttk objects, and the widgets also teared when I added frames. Here is the code I tried.

      from tkinter import *
      from tkinter import ttk
      
      paned = ttk.Panedwindow(orient="horizontal")
      left = ttk.Frame(paned)
      left.pack(side='left', fill='both', expand=True)
      right = ttk.Frame(paned)
      right.pack(side='right', fill='both', expand=True)
      button = ttk.Button(left,text="lefgt pane")
      button.pack( fill='both', expand=True)
      button2 = ttk.Button(right, text="right pane")
      button2.pack( fill='both', expand=True)
      paned.add(left)
      paned.add(right)
      paned.pack(fill="both",expand=True, pady = (4,1), padx=4)
      
      mainloop()
    13. LitaCho commented on Jul 4, 2014

      LitaChomannequin
      Mannequin

      Should I file a bug? I feel like this a bug specifically related to Python 3 and Tkinter.

    14. ned-deily commented on Jul 4, 2014

      @ned-deily
      Member

      If by tearing you mean leaving artifacts on the screen, differences in behavior are almost certainly due to different versions of Tk being used. Tkinter is really just a wrapper around calls to Tk; nearly all of the heavy-duty graphics work is done by Tk making calls to other, platform-specific graphics libraries. FWIW, I ran your last test with the current python.org 2.7.8 and 3.4.1 on OS X with the current ActiveTcl Tk 8.5.15 and they both performed identically: I expanded the frame to fill the screen and could cleanly move the slider to the left or right with no artifacts.

    15. 20 remaining items

    16. terryjreedy commented on Jul 7, 2014

      @terryjreedy
      MemberAuthor

      I don't really know what most beginners will expect. Perhaps an entry in the help will be enough. I would like have a better how to use summary at the top of the file anyway.

      If I swish the normal cursor across the divide, it jumps from I-bar on text side to arrow on canvas side without even displaying the two-headed arrow. Checking with a magnifying glass, I have to pause the cursor in the 3 pixels wide gray shadow of the solid black line*. (The And even then, the cursor does not always switch. Since this patch does not use ttk, I will try 'showhandle=True' and see how it looks and behaves.

      The shadow is not normal for Windows divider lines. It would be better is if could be turned off. The 'sensitive' zone of about 3 (maybe 4) pixels to the right or under the line seems to be normal.

    17. LitaCho commented on Jul 7, 2014

      LitaChomannequin
      Mannequin

      Hi Terry,

      So the shadow can easily be removed. I just went with the default sashrelief style. I am going to attach two patches with different sashrelief styles, both of which don't have the shadow.

    18. LitaCho commented on Jul 7, 2014

      LitaChomannequin
      Mannequin

      I personally like the FLAT look because it matches with the rest of the GUI.

    19. LitaCho commented on Jul 21, 2014

      LitaChomannequin
      Mannequin

      Ping! Just wanted to see what the status was on getting this patch reviewed. I hope your eye is feeling better, Terry!

    20. terryjreedy commented on Jul 22, 2014

      @terryjreedy
      MemberAuthor

      For me, FLAT is about as mushy as the default, while SOLID actually looks like a divider. I find the sash easier to 'grab' and move. I plan to go with that. If it looks substantially worse on some other system, we could make the argument conditional on sys.platform or whatever.

      I plan to do a 'final' review in the next day and either commit or post a revision for testing on non-Windows systems.

    21. terryjreedy commented on Jul 23, 2014

      @terryjreedy
      MemberAuthor

      I reviewed code and made the following changes in uploaded file:
      Move some code and blank lines around.
      Since you left packing within mBar frame, removed
      self.mBar.grid_columnconfigure(0, weight=1)
      Since the only thing packed in the left frame was the text frame, renamed makeLeftFrame to makeTextFrame, removed the left frame and returned the text frame to be gridded directly. Works fine.
      Remove left_frame, graph_frame temporaries.

      The questions that stopped me from pushing this are about the following lines in makeGraphicFrame.

              self._canvas = turtle.ScrolledCanvas(root,
                                                   800, 600,
                                                   self.canvwidth, self.canvheight)
              turtle._Screen._canvas = self._canvas #*
              turtle._Screen._canvas.adjustScrolls()
              turtle._Screen._canvas._rootwindow.bind('<Configure>', self.onResize)
              turtle._Screen._canvas._canvas['borderwidth'] = 0
              turtle._Screen._canvas.grid(row=0, column=0, sticky='news') ##
              ...
              return  turtle._Screen._canvas

      It seems that in all lines except #*, 'turtle._Screen._canvas' could be replaced by 'self._canvas' or even a 'canvas' temporary. The ## line seems wrong, as the parent is root and 0,0 is not where the canvas shoud be gridded and indeed not where it is gridded after being returned. The demo seems fine after commenting out the line. So it seems that the following should work.

              self._Screen._canvas = self._canvas = canvas = (
                      turtle.ScrolledCanvas(
                      root, 800, 600, self.canvwidth, self.canvheight))
              canvas.adjustScrolls()
              canvas._rootwindow.bind('<Configure>', self.onResize)
              canvas._canvas['borderwidth'] = 0
              ...
              return  canvas

      Am I missing something? Just curious, what is the <Configure> event? Or rather, what generates it?

    22. LitaCho commented on Jul 23, 2014

      LitaChomannequin
      Mannequin

      On Tue, Jul 22, 2014 at 8:20 PM, Terry J. Reedy <report@bugs.python.org>
      wrote:

      Terry J. Reedy added the comment:

      I reviewed code and made the following changes in uploaded file:
      Move some code and blank lines around.
      Since you left packing within mBar frame, removed
      self.mBar.grid_columnconfigure(0, weight=1)
      Since the only thing packed in the left frame was the text frame, renamed
      makeLeftFrame to makeTextFrame, removed the left frame and returned the
      text frame to be gridded directly. Works fine.
      Remove left_frame, graph_frame temporaries.

      The questions that stopped me from pushing this are about the following
      lines in makeGraphicFrame.

          self.\_canvas = turtle.ScrolledCanvas(root,
                                               800, 600,
                                               self.canvwidth,
      

      self.canvheight)
      turtle._Screen._canvas = self._canvas #*
      turtle._Screen._canvas.adjustScrolls()
      turtle._Screen._canvas._rootwindow.bind('<Configure>',
      self.onResize)
      turtle._Screen._canvas._canvas['borderwidth'] = 0
      turtle._Screen._canvas.grid(row=0, column=0, sticky='news') ##
      ...
      return turtle._Screen._canvas

      It seems that in all lines except #*, 'turtle._Screen._canvas' could be

      replaced by 'self._canvas' or even a 'canvas' temporary. The ## line seems
      wrong, as the parent is root and 0,0 is not where the canvas shoud be
      gridded and indeed not where it is gridded after being returned. The demo
      seems fine after commenting out the line. So it seems that the following
      should work.

          self.\_Screen.\_canvas = self.\_canvas = canvas = (
                  turtle.ScrolledCanvas(
                  root, 800, 600, self.canvwidth, self.canvheight))
          canvas.adjustScrolls()
          canvas.\_rootwindow.bind('\<Configure\>', self.onResize)
          canvas.\_canvas['borderwidth'] = 0
          ...
          return  canvas
      

      Yes! I like this a lot better. turtle._Screen._canvas was how the canvas
      was being manipulated before. I was trying to follow the original
      programmer's convention, but that works perfectly!

      Am I missing something? Just curious, what is the <Configure> event? Or
      rather, what generates it?

      The Configure event is triggered when the widget changes size. It is super
      confusing. Look for '<Configure>' in the documentation here:

      http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

      I had to override Turtle's onResize metbod because the canvas wasn't
      centering properly when the sash was being moved.

      ----------


      Python tracker <report@bugs.python.org>
      <http://bugs.python.org/issue21597\>


    23. LitaCho commented on Jul 23, 2014

      LitaChomannequin
      Mannequin

      Just to clarify, should I submit a new patch with outlined style changes?

    24. python-dev commented on Jul 23, 2014

      python-devmannequin
      Mannequin

      New changeset 60301b9982b2 by Terry Jan Reedy in branch '2.7':
      Issue bpo-21597: Turtledemo text pane can now be widened to view or copy complete
      http://hg.python.org/cpython/rev/60301b9982b2

      New changeset 0fb515063324 by Terry Jan Reedy in branch '3.4':
      Issue bpo-21597: Turtledemo text pane can now be widened to view or copy complete
      http://hg.python.org/cpython/rev/0fb515063324

    25. terryjreedy commented on Jul 23, 2014

      @terryjreedy
      MemberAuthor

      No, I believe this is done ;-). Onward to font sizing.
      Thank you for the hard work on this. It is a great improvement.

    26. LitaCho commented on Jul 23, 2014

      LitaChomannequin
      Mannequin

      Sweet! Thank you so much, Terry!

      On Wednesday, July 23, 2014, Terry J. Reedy <report@bugs.python.org> wrote:

      Terry J. Reedy added the comment:

      No, I believe this is done ;-). Onward to font sizing.
      Thank you for the hard work on this. It is a great improvement.

      ----------
      resolution: -> fixed
      stage: commit review -> resolved
      status: open -> closed


      Python tracker <report@bugs.python.org <javascript:;>>
      <http://bugs.python.org/issue21597\>


    27. terryjreedy commented on Jul 23, 2014

      @terryjreedy
      MemberAuthor

      Lita, when replying by email, please, please delete the message you are replying to (except possibly for a directly quoted line or two).

    28. LitaCho commented on Jul 23, 2014

      LitaChomannequin
      Mannequin

      Sorry about that!! Thanks for letting me know.

    29. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions