I have a Dell 2-in-1 computer that I can use as a tablet, and I'm working on a script to resize the window of an application base on the orientation of the display. What I'm trying to do is get an assigned variable monitor = Monitor()
to return itself as a tuple in a match case comparison.
from win32api import GetMonitorInfo, MonitorFromPoint
from typing import Optional
class Monitor:
def __init__(self):
self._monitor: Optional[tuple] = None
self.update()
@property
def Width(self) -> int:
return self._monitor[0]
@property
def Height(self) -> int:
return self._monitor[1]
def update(self):
self._monitor = self()
def __call__(self) -> tuple:
return GetMonitorInfo(MonitorFromPoint((0, 0)))['Monitor'][2:]
def __iter__(self):
return iter(self._monitor)
def __next__(self):
return tuple(self._monitor)
def __getitem__(self, index):
return self._monitor[index]
def __eq__(self, other):
return self._monitor == other
def __str__(self):
return str(self._monitor)
def __repr__(self):
return str(self._monitor)
if __name__ == '__main__':
monitor = Monitor()
print(f'monitor: {monitor}')
match monitor:
case (1440, 900):
print((1440, 900))
case (900, 1440):
print((900, 1440))
For several days, I've read through posts here on stackoverflow.com, and I've been searching through Google search looking for code examples, but I haven't found anything. I do know that the class.__call__
will give me what I want, but in this class, the __call__
is to get the current resolution of the monitor so I can compare the class against itself monitor == monitor()
. With Windows 11 Tablet Mode, the touch screen will rotate with the computer the same way a touch screen does on an Android device.
To match a sequence pattern (which is what you're getting with case (1440, 900)
and the reverse), you need your class to inherit from collections.abc.Sequence
(see this footnote in the docs for match
statement), or be registered as a subclass without actually inheriting (with collections.abc.Sequence.register(Monitor)
). Just implementing the __getitem__
method is not enough. (Note, you also need a __len__
method to actually be a valid sequence.)
If you're willing to adjust your patterns, you could make the current form of your class work. Try something like this:
case Monitor(Width=1440, Height=900)):
Note that class patterns like this are written as if each named attribute can be passed as an argument when constructing an instance. This isn't actually true for your class, but it doesn't matter that the actual __init__
method doesn't take Width
or Height
, the match
will still work.
That said, the monitor == monitor()
design seems pretty weird. It might make more sense to create a second instance, rather than calling the first one to get an updated resolution tuple. Then compare the two monitor instances:
old_monitor = Monitor()
# later, when you want to check if the orientation has changed:
new_monitor = Monitor()
if old_monitor != new_monitor:
# rotate...