How to find easily the location of mouse in terms of lines ?

Hi,

I have a window (wx.lib.scrolledpanel.ScrolledPanel) that displays some data.
I want to let the user double-click on a line, which would trigger an event which will open another window (that will display some additional data related to the line that was double-clicked).

Is there an easy way to know on which line in the window I am, regardless of which font I use ?
Namely, is there a way to know the location the mouse is in the window in terms of lines and characters from the beginning of line ?

(AFAIK, the event.GetX()/event.GetY() gives the location in pixels, and one needs to translate them to lines/characters by knowing the characteristics of the font used.)

Thanks,
Ron.

I have a window (wx.lib.scrolledpanel.ScrolledPanel) that displays some data.

I want to let the user double-click on a line, which would trigger an event which will open another window (that will display some additional data related to the line that was double-clicked).

Is there an easy way to know on which line in the window I am, regardless of which font I use ?

Namely, is there a way to know the location the mouse is in the window in terms of lines and characters from the beginning of line ?

How is the data display managed? Do you have a big statictext ctrl in there or lots of little controls – or an OnPaint handler that is printing into the ScrolledPanel?

I’m doing a Grand Experiment (ahem) of a sorta hyper-customized listctrl that’s entirely owner-drawn, and I ran into an issue which is similar: needing to hit test vs specific lines and cells in displayed records. Since I’m doing all of the display on an OnPaint handler, I store the location of each discrete line as an (x, y, width, height) tuple as I draw it.

So as I’m drawing, I calculate the current lines (x, y, width, height) – because I need to do a dc.DrawRectangle anyways, and I just store it after I draw it. Later, I get the Y coordinates of the click and iterate over my cached box rects to find which line I’m in… then I iterate over the lines columns/cells to determine which the X click-coordinate it fits in. It actually seems to perform pretty well. I’m sure there’s a better way but I haven’t been able to come up with it yet (primarily because in my scenario, the row heights are variable)

In your scenario, if you’re painting all the “lines and characters” at the time of painting you can use dc.GetTextExtent and store the coordinates/rects of individual items for scanning in your hit test code later.

Don’t know if that’s any use as its slightly vague, and there might be some Grand Better Way To Do It, but HTH :slight_smile:

–Stephen

Barak, Ron wrote:

I have a window (wx.lib.scrolledpanel.ScrolledPanel) that displays some data.
I want to let the user double-click on a line, which would trigger an event which will open another window (that will display some additional data related to the line that was double-clicked).

how are your "lines" getting drawn to the Panel?

If you're using DCs or GCs, then you need to keep track of where everything is yourself, and figure out which line a given pixel coord is.

There are essentially two ways to do this:

1) use math -- and if your lines are all recatngels, that's pretty easy.

2) when you draw your lines, you can also draw the rectangle of that line in a particular color in another, off-screen, bitmap. then you can check the color of the pixel to see which line it is -- that's how FloatCanvas does hit-testing.

I suspect (1) is easier if your lines are as structured as they sound.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Hi Stephen,

scrolling_demo.py (1.44 KB)

···

From: Stephen Hansen
Sent:
Wednesday, January 21, 2009 18:55
To:
wxpython-users@lists.wxwidgets.org
Subject: Re: [wxpython-users] How to find easily the location of mouse in terms of lines ?

I have a window (wx.lib.scrolledpanel.ScrolledPanel) that displays some data.
I want to let the user double-click on a line, which would trigger an event which will open another window (that will display some additional data related to the line that was double-clicked).

Is there an easy way to know on which line in the window I am, regardless of which font I use ?
Namely, is there a way to know the location the mouse is in the window in terms of lines and characters from the beginning of line ?

How is the data display managed? Do you have a big statictext ctrl in there or lots of little controls – or an OnPaint handler that is printing into the ScrolledPanel?
[BR] The distilled code is attached. I do nothing fancy, just putting a single wx.StaticText on a ScrolledPanel.
The scenario you outline below is exactly the one I’m trying to avoid :wink:

Actually, I’d be happy with just knowing the row the mouse is clicking on.
(I understand that on a proportional font, calculating the character the mouse is on is more involved. I can live without this knowledge).

Thanks,
Ron.

I’m doing a Grand Experiment (ahem) of a sorta hyper-customized listctrl that’s entirely owner-drawn, and I ran into an issue which is similar: needing to hit test vs specific lines and cells in displayed records. Since I’m doing all of the display on an OnPaint handler, I store the location of each discrete line as an (x, y, width, height) tuple as I draw it.

So as I’m drawing, I calculate the current lines (x, y, width, height) – because I need to do a dc.DrawRectangle anyways, and I just store it after I draw it. Later, I get the Y coordinates of the click and iterate over my cached box rects to find which line I’m in… then I iterate over the lines columns/cells to determine which the X click-coordinate it fits in. It actually seems to perform pretty well. I’m sure there’s a better way but I haven’t been able to come up with it yet (primarily because in my scenario, the row heights are variable)

In your scenario, if you’re painting all the “lines and characters” at the time of painting you can use dc.GetTextExtent and store the coordinates/rects of individual items for scanning in your hit test code later.

Don’t know if that’s any use as its slightly vague, and there might be some Grand Better Way To Do It, but HTH :slight_smile:

–Stephen

Barak, Ron wrote:

    [BR] The distilled code is attached. I do nothing fancy, just
    putting a single wx.StaticText on a ScrolledPanel.
    The scenario you outline below is exactly the one I'm trying to
    avoid :wink:
         Actually, I'd be happy with just knowing the row the mouse is
    clicking on.

Well, a StaticText is designed to be just hat -- static -- it can't do much.

You can use a wx.TextCtrl instead. However, it's still harder than is should be. It looks like wx.TextCtrl.HitTest() does what you want, but it doesn't work on a Mac, where I am testing now.

How would you do this on a Mac?

Enclosed is a sample...

-Chris

scrolling_demo.py (1.97 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

How is the data display managed? Do you have a big statictext ctrl in there or lots of little controls – or an OnPaint handler that is printing into the ScrolledPanel?

[BR] The distilled code is attached. I do nothing fancy, just putting a single wx.StaticText on a ScrolledPanel.
The scenario you outline below is exactly the one I’m trying to avoid :wink:

Actually, I’d be happy with just knowing the row the mouse is clicking on.
(I understand that on a proportional font, calculating the character the mouse is on is more involved. I can live without this knowledge).

I was able to get the row / line fairly readily – I tried to then get the character and failed :wink: It worked just fine in the main part of the window but started skewing oddly in the scrolled portion.

In an EVT_LEFT_UP handler, I did:

    y = event.GetY()
    _, lineHeight = self.st1.GetTextExtent("X")

    lineNo = y / lineHeight
    print "Line: #", lineNo, "-->", self.text[lineNo]

Where self.st1 and self.text were the objects you created in your StaticText frame.

Hello Chris,
Looking at the widgets wxPython have, I decided that a wx.ListCtrl might be better suited to my needs.
Not all is rosy: I'm having problems seamlessly using wx.ListCtrl and wx.lib.scrolledpanel.ScrolledPanel, but,
at least, the EVT_LIST_ITEM_SELECTED is able to give me the text of the line I'm on, so - I guess I'm on the right path.
Bye,
Ron.

···

-----Original Message-----
From: Christopher Barker [mailto:Chris.Barker@noaa.gov]
Sent: Thursday, January 22, 2009 21:44
To: wxpython-users@lists.wxwidgets.org
Subject: Re: [wxpython-users] How to find easily the location of mouse in terms of lines ?

Barak, Ron wrote:

    [BR] The distilled code is attached. I do nothing fancy, just
    putting a single wx.StaticText on a ScrolledPanel.
    The scenario you outline below is exactly the one I'm trying to
    avoid :wink:

    Actually, I'd be happy with just knowing the row the mouse is
    clicking on.

Well, a StaticText is designed to be just hat -- static -- it can't do much.

You can use a wx.TextCtrl instead. However, it's still harder than is should be. It looks like wx.TextCtrl.HitTest() does what you want, but it doesn't work on a Mac, where I am testing now.

How would you do this on a Mac?

Enclosed is a sample...

-Chris

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov