2023年9月17日日曜日

「MX MASTER 2S」が不調なので修理してみた

こんにちは、やっまむーです。

先日、自宅で使用しているマウス「MX MASTER 2S」が急に動かなくなりました。
ポインタが動かず、しかしクリック操作やスクロールは問題なし。
電源を入れなおしたり、無線の接続設定を見直したりと試しましたがうんともすんともポインタは動きません。

キーボード操作のみを駆使して調べてみると、どうやら内部パーツの劣化により一部のボタンが押しっぱなしになっていることが原因のようです。
保証書を確認すると2017年に購入しており、6年間使い続ければ仕方ないなとも思います。

ただ、同等品の「MX MASTER 3S」は1万円を超える価格なのでポンとお金を出すのを躊躇してしまいます。
さらに調べてみると、同様の現象に悩まされて自己修理をしたという記事を見つけましたので、今回はそれにならって私も修理してみました。

分解と修理手順

使う工具は大きく3つです。

  • カッターナイフ(ソール剥がし用)
  • T型トルクスドライバーのT5サイズ
  • プラスドライバーのNo.0サイズ

まずはマウスの滑りをよくするソールをカッターナイフで剥がします。 刃先を隙間に差し込んで剥がしていきます。 今回、ソールを再利用するため破損しないようにゆっくりと、また接着面をできるだけ触れないようにピンセットも使っています。

ソールがあった個所はプラスドライバー、マウスの先端部はトルクスドライバーを使って外します。 自宅にトルクスドライバーが無かったので、急遽精密ドライバーのセットをAmazonで購入しました。

ネジを外して中身を開けるとこのようになっています。 フレキケーブルが繋がっているので勢いよく開けると断線の可能性もあります。

今回、親指部分にあるジェスチャーボタンが押されっぱなしになっています。 この部分のネジを緩めることで、ボタンと基盤のスイッチ部に隙間を作ってやります。

作業完了後は元通りにねじ止めしてソールを張り付けて完成。 電源を入れると、無事にマウスが動くようになりました。

今回保障期間も過ぎており、最悪買い替えればと考えて分解修理をしました。 皆さんも壊れた機器があれば自分で修理してみてはいかがでしょうか。

キーボードでマウスを操作する

ちなみに予備マウスがないため、調べるときはキーボード操作のみで行っていました。 その中で、どうしてもマウス操作が必要な時は「アクセシビリティ マウスの設定」でテンキーによるマウス操作を使いました。

Windowsキーを押して、「アクセシビリティ マウスの設定」と検索すると設定が出てきます。

タブキーを押して「マウス キー機能」まで移動して設定をオンにすると、テンキーでポインタを操作できるようになります。 普段使う機会はないと思いますが、もしもの時は使ってみることをお勧めします。

ではではー。

2023年9月3日日曜日

[Python]Tkinter Treeviewの値取得でゼロ落ち

こんばんは。ざわです。

Pythonで実装したツールで、画面の一覧データをCSVファイルに出力したら
頭に0(ゼロ)がついているデータの 0部分がゼロ落ちして出力される現象がありました。
GUIにtkinter、一覧(表)は tkinter.ttk.Treeview ウィジェットを使っています。
原因など調べてみた結果と対応策について書いていきたいと思います。

現象

ゼロ落ち現象となるサンプルコードはこちらになります。

# サンプルコード
import tkinter as tk
from tkinter import ttk
import pandas as pd

# CSV出力ボタン押下
def btnCsvOutput_Click():  
    data = [tree.item(item)['values'] for item in tree.get_children()]
    df = pd.DataFrame(data)
    df.to_csv('sample.csv', encoding='shift-jis', header=False, index=False)

# メインウィンドウ生成
root = tk.Tk()
root.title('sample')
root.geometry('400x300')

# Treeview
column = ('ID', 'Name')
tree = ttk.Treeview(root, columns=column)
# 列設定
tree.column('#0',width=0, stretch='no')
tree.column('ID', anchor='w', width=100)
tree.column('Name',anchor='w', width=100)
# 列見出し設定
tree.heading('#0',text='')
tree.heading('ID', text='ID',anchor='w')
tree.heading('Name', text='Name', anchor='w')
# レコード追加
tree.insert(parent='', index='end', iid=0 ,values=('00001', 'AAAAA'))
tree.insert(parent='', index='end', iid=1 ,values=('00100', 'BBBBB'))
tree.insert(parent='', index='end', iid=2 ,values=('000XXXXX', 'CCCCC'))

# ウィジェット配置
tree.pack(pady=10)

btnCsvOutput = tk.Button(root, text='CSV出力', width=10, command=btnCsvOutput_Click)
btnCsvOutput.pack(pady=10)

root.mainloop()

これを実行した画面がこちら。

CSV出力した結果がこちら。

画面の表のID列には コードの29~31行目のレコード追加処理で書いた通り 0がついた状態で表示されていますが、
CSVには 0が消えて出力されています。
ただ、CSVの3行目のように 数値以外の文字が含まれる場合はゼロ落ちしていません。

対応方法

さて、何が原因でどう修正したらいいかなと調べた結果、こちらのサイトが参考になりました。

(フォーマットして0埋めしたら?というご意見もあると思いますが桁数が固定でないためフォーマットでは対処できず・・)

原因は、tkinter.ttk.Treeviewでは、整数に変換できる文字列は整数に変換してしまうようで、
それに該当するのが ttkの _convert_stringval()関数(*1)のようです。

参考サイトでは、
自身のコードに、条件文によって整数に変換しない _convert_stringval()関数を実装し、
ttk._convert_stringvalをその関数で置き換えるようにしています。(*2)

*1:ttk.py の元の関数
def _convert_stringval(value):
    """Converts a value to, hopefully, a more appropriate Python object."""
    value = str(value)
    try:
        value = int(value)
    except (ValueError, TypeError):
        pass

    return value
 ttk.py はPythonのインストール先の tkinterフォルダにあります。
 (例 : C:\Users\{ユーザID}\AppData\Local\Programs\Python\Python310\Lib\tkinter)

*2:上記のサンプルコードに _convert_stringval()関数を追加した例
# サンプルコード
import tkinter as tk
from tkinter import ttk
import pandas as pd

def _convert_stringval(value):
    """Converts a value to, hopefully, a more appropriate Python object."""
    if hasattr(value, 'typename'):
        value = str(value)
        try:
            value = int(value)
        except (ValueError, TypeError):
            pass
    return value

ttk._convert_stringval = _convert_stringval

# CSV出力ボタン押下
def btnCsvOutput_Click():  
    data = [tree.item(item)['values'] for item in tree.get_children()]
    df = pd.DataFrame(data)
    df.to_csv('sample.csv', encoding='shift-jis', header=False, index=False)

# メインウィンドウ生成
root = tk.Tk()
root.title('sample')
root.geometry('400x300')

(以下略)

6~14行目に _convert_stringval()関数を追加しています。
(この関数は、ttkのimport後、ttk.Treeviewを使用するコードより前に追加すること)
8行目の if文が元関数から変更(追記)したコードになります。
16行目で ttk._convert_stringval を自身の関数で置き換えています。

これを実行してCSV出力した結果がこちら。

ID列のデータがゼロ落ちせず、正しく出力されるようになりました。

ここまで、ttk._convert_stringval()関数を変更する方法を書いてきましたが、
他のコードに影響を及ぼしそうでttkの関数を変更したくない、という場合もあるかと思います。
そういった場合の対応案として、Treeviewにinsertする時点でデータを pandasのDataFrameにセット(保持)しておき、
CSV出力処理時に Treeviewから出力データを取得するのではなく、保持したDataFrameデータを出力すればいいかと思います。

それではまたー。