この記事の例では、Java で画面共有機能を実装する方法を説明します。皆さんの参考に共有してください。具体的な分析は次のとおりです。
最近、私はソフトウェアエンジニアリングのコースを設計し、研究室の画面監視システムを作成し、さまざまな先行コードを参照し、最終的に理解した後に自分のコードを変換するのを初心者が真似する方法です。
画面監視システムには教師側と生徒側があり、教師側がサーバー側、生徒側がクライアント側となります。このシステムの最も興味深い点の 1 つは、おそらく、画面ブロードキャストと画面監視です。残りの点呼、画面ロック、およびスケジュールされたシャットダウンは比較的単純です。
画面ブロードキャストとは、機能実装としては、端的に言えば、教師のマシンが画面情報を継続的に傍受し、それを写真の形で各生徒のコンピューターに送信し、生徒がコンピューター上で教師の操作を確認できるようにすることです。いわゆるスクリーンブロードキャスト。
ここで厄介なのが、画面のスクリーンショットを撮る際にマウスの情報が無いことです。しかし、解決策は 2 つあります。
① スクリーンショット情報を送信する場合、生徒側にマウスが 2 つになるように絵上にマウスを描き、生徒側は自分のコンピュータ上でマウスを動かすことができます。
②教師側のマウス座標を生徒側に送信し、その座標情報に従って生徒のコンピュータのマウスがリアルタイムに動きます。これは実際には制御機能があり、生徒側ではマウスを動かすことができません。
画面監視は比較的扱いが難しいのですが、実際には次の 2 つの機能が含まれています。
①教師は生徒全員のコンピュータ画面を監視できます。
②教師は生徒のコンピュータを制御します。
並行処理が必要となるため、各クライアントからリアルタイムで画面情報を教師に送信する必要があり、少々面倒ではありますが、それでも実現可能です。
ここでは、マウスを使用しない画面共有機能を一時的に実装します。比較的シンプルであり、改善の必要がありますが、後で統合するためのツール クラスとして使用できます。
1 つ目は教師サーバーです。
次のようにコードをコピーします。
java.awt.Dimensionをインポートします。
java.awt.Rectangle をインポートします。
java.awt.Robotをインポートします。
java.awt.Toolkitをインポートします。
インポート java.awt.image.BufferedImage;
java.io.DataOutputStreamをインポートします。
インポート java.io.IOException;
java.net.ServerSocketをインポートします。
java.net.Socketをインポートします。
java.util.zip.ZipEntryをインポートします。
インポート java.util.zip.ZipOutputStream;
インポートjavax.imageio.ImageIO;
/*
* 2014 年 11 月 20 日
* このタイプのスクリーンショットのリアルタイム送信はなくなり、マルチスレッド実装になり、マウス情報は含まれず、各クライアントは最適化されません。
*/
パブリッククラスSendScreenImgはThreadを拡張します
{
public static int SERVERPORT=8000;
プライベートサーバーソケットサーバーソケット;
プライベートロボットロボット。
公開寸法画面。
パブリック Rectangle 長方形;
private Socket ソケット。
public static void main(String args[])
{
new SendScreenImg(SERVERPORT).start();
}
//ソケット接続ロボットを開いて画面サイズを取得する構築メソッド
public SendScreenImg(int SERVERPORT)
{
試す {
サーバーソケット = 新しいサーバーソケット(サーバーポート);
サーバーソケット.setSoTimeout(864000000);
ロボット = 新しいロボット();
} catch (例外 e) {
e.printStackTrace();
}
screen = Toolkit.getDefaultToolkit().getScreenSize(); //メイン画面のサイズを取得します。
rect = new Rectangle(screen) // 画面サイズの長方形を作成します。
}
@オーバーライド
public void run()
{
// スクリーンショット メッセージの受信をリアルタイムで待機します
その間(真)
{
試す{
ソケット = サーバーソケット.accept();
System.out.println("学生ポートが接続されています");
ZipOutputStream zip = new ZipOutputStream(new DataOutputStream(socket.getOutputStream()));
zip.setLevel(9); //圧縮レベルを設定します。
BufferedImage img = robot.createScreenCapture(rect);
zip.putNextEntry(new ZipEntry("test.jpg"));
ImageIO.write(img, "jpg", zip);
if(zip!=null)zip.close();
System.out.println("クライアントはリアルタイムで接続しています");
キャッチ (IOException ioe) {
System.out.println("接続が切断されました");
} ついに {
if (ソケット != null) {
試す {
ソケット.クローズ();
catch (IOException e) {e.printStackTrace();}
}
}
}
}
}
次に、学生クライアントがあります。
次のようにコードをコピーします。
java.awt.Frameをインポートします。
java.awt.Imageをインポートします。
インポート java.awt.event.WindowAdapter;
インポートjava.awt.event.WindowEvent;
インポートjava.io.DataInputStream;
インポート java.io.IOException;
java.net.Socketをインポートします。
java.util.concurrent.TimeUnitをインポートします。
インポート java.util.zip.ZipInputStream;
インポートjavax.imageio.ImageIO;
インポート javax.swing.ImageIcon;
javax.swing.JFrameをインポートします。
インポートjavax.swing.JLabel;
/*
* 2014 年 11 月 20 日
※このクラスはマウスを除く教師側の画面情報を受け取るために使用するため、最適化が必要です。
*/
public class ReceiveImages extends Thread{
パブリック BorderInit フレーム。
public Socket ソケット。
パブリック文字列IP;
public static void main(String[] args){
new ReceiveImages(new BorderInit(), "127.0.0.1").start();
}
public ReceiveImages(BorderInit フレーム、文字列 IP)
{
this.frame = フレーム;
this.IP=IP;
}
public void run() {
while(frame.getFlag()){
試す {
ソケット = 新しいソケット(IP,8000);
DataInputStream ImgInput = new DataInputStream(socket.getInputStream());
ZipInputStream imgZip = 新しい ZipInputStream(ImgInput);
imgZip.getNextEntry(); //Zip ファイル ストリームの先頭に移動します。
Image img = ImageIO.read(imgZip); //Zip イメージ ストリーム内のイメージをバイト数に従って読み取ります。
Frame.jlbImg.setIcon(new ImageIcon(img));
System.out.println("接続番号"+(System.currentTimeMillis()/1000)%24%60+"秒");
フレーム.検証();
TimeUnit.MILLISECONDS.sleep(50);//画像受信間隔時間
imgZip.close();
catch (IOException | InterruptedException e) {
System.out.println("接続が切断されました");
}ついに{
試す {
ソケット.クローズ();
キャッチ (IOException e) {}
}
}
}
}
//クライアント側のウィンドウ補助クラス。特に教師側から受け取った画面情報を表示するために使用されます。
クラス BorderInit は JFrame を拡張します
{
プライベート静的最終ロングシリアルバージョンUID = 1L;
パブリック JLabel jlbImg;
プライベートブールフラグ。
public boolean getFlag(){
this.flag を返します。
}
publicBorderInit()
{
this.flag=true;
this.jlbImg = 新しい JLabel();
this.setTitle("リモート監視--IP:" + "--トピック:" );
this.setSize(400, 400);
//this.setUndecorated(true); //全画面表示、テスト時はコメントアウトするのが最善です
//this.setAlwaysOnTop(true); //表示ウィンドウは常に前面に表示されます。
this.add(jlbImg);
this.setLocationRelativeTo(null);
this.setExtendedState(Frame.MAXIMIZED_BOTH);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setVisible(true);
this.validate();
//ウィンドウクローズイベント
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
フラグ = false;
BorderInit.this.dispose();
System.out.println("フォームを閉じました");
System.gc(); //ガベージコレクション
}
});
}
}
ここにあるのは未完成の製品から抽出した小さな機能です。興味のある友人がこれをベースに改良できるようになるまで、まだ書くことがたくさんあります。
この記事が皆さんの Java プログラミングに役立つことを願っています。