Grafik Darstellung

  • Antworten:41
  • Bentwortet
PBahner
  • Forum-Beiträge: 40

12.10.2018, 23:03:36 via Website

Hallo,
zurzeit arbeite ich an einer App, über die ich meine Modelleisenbahn steuern kann. Dabei möchte ich angezeigt bekommen, wo sich ein Zug befindet und wie eine Weiche gestellt ist. Dazu habe ich mir einen Gleisplan erstellt, auf dem alle Gleise frei sind und die Weichen nicht eingezeichnet sind. Das ist mein Hintergrund der App. Wenn ein Zug auf einem Gleis steht soll der Gleisabschnitt von gelb auf Rot die Farbe ändern. Dazu habe ich ein View mit der Farbe Rot auf das gelbe Gleis platziert, welches sich bei verschiedenen Größen vom Display verschiebt. Wie kann ich es lösen, dass das View genau auf dem gelben Gleis sich befindet? Oder gibt es eine einfachere Lösung, wie ich das realisieren kann? Außerdem verzerrt sich der Hintergrund bei verschiedenen Displaygrößen. Wie geht es, dass das Hintergrundbild sich nicht verzerrt?
Hier noch ein Screenshot der Appimage

Mfg. PBahner

Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.530

13.10.2018, 11:32:44 via Website

Ich meinte nicht das du für jede Kombination ein Bild machen sollst.
Sondern du sollst kein Hindergrundbild nehmen .
Du sollst das Bild Programmatisch zur Laufzeit erzeugen mit Grafik Methoden wie Line Zeichner, Kreis, Rechteck, Kreisbogen, so wie eine Vektorgrafik. Nicht in Exel Zeichen und nur anzeigen das wird immer Probleme geben.

Kannst ja Trotzdem ein fertiges Bild in dein Bitmap Laden und nur die Gleis abschnitte darüber zeichnen muss das halt Pixel genau sein so wie im Bild , und dieses Bitmap läst du in deiner View anzeigen.
Denke dafür ist es am besten wenn du von View, ImageView oder was du meinst eine Klasse ableitest und in ihr die onDraw Methode Überschreibst. Und genau dort in das Canvas dein gezeichnetes Bitmap lädst .

Im layout benutzt du dann deine eigene View.

Das währe mein Vorschlag, knapp erklärt.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

13.10.2018, 08:30:16 via Website

Hallo wie hast du denn das Bild gemacht?

Ich würde ein Bitmap erstellen Inder passenden Größe und deine Strecken mit Hilfe von canvas Grafik funktionieren auf die bitmap zeichnen. Dann kannst du wenn sich die Farbe eines Abschnittes ändern soll. Einfach diesen Bereich beim neu zeichnen in einer anderen Farbe darstellen.

Oder du baust dir die Grafik aus mehreren drawable zusammen und erstellst die in verschiedenen Farben.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

13.10.2018, 09:44:11 via Website

Hallo Jokel
Den Gleisplan habe ich mit Excel erstellt. Dort habe ich dann die Signale als Bilder eingefügt. Ich möchte nicht für jede Veränderung der Farbe ein neues Hintergrund Bild einfügen, da es sonst bis zu über 60 Bilder werden könnten. Die App soll auf verschiedenen Geräten laufen, sodass es viel zu umständlich wäre für jedes Gerät ein Hintergrund Bild mit passender Größe zu erstellen.
Erkläre mir bitte genauer, wie ich aus mehreren drawable eine Grafik zusammen bauen kann.

Hilfreich?
Kommentieren
Beste Antwort
Jokel
  • Forum-Beiträge: 1.530

13.10.2018, 11:32:44 via Website

Ich meinte nicht das du für jede Kombination ein Bild machen sollst.
Sondern du sollst kein Hindergrundbild nehmen .
Du sollst das Bild Programmatisch zur Laufzeit erzeugen mit Grafik Methoden wie Line Zeichner, Kreis, Rechteck, Kreisbogen, so wie eine Vektorgrafik. Nicht in Exel Zeichen und nur anzeigen das wird immer Probleme geben.

Kannst ja Trotzdem ein fertiges Bild in dein Bitmap Laden und nur die Gleis abschnitte darüber zeichnen muss das halt Pixel genau sein so wie im Bild , und dieses Bitmap läst du in deiner View anzeigen.
Denke dafür ist es am besten wenn du von View, ImageView oder was du meinst eine Klasse ableitest und in ihr die onDraw Methode Überschreibst. Und genau dort in das Canvas dein gezeichnetes Bitmap lädst .

Im layout benutzt du dann deine eigene View.

Das währe mein Vorschlag, knapp erklärt.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

13.10.2018, 12:03:54 via Website

Danke dir!
Die Canvas Klasse mit den "Draw" Methoden kannte ich bisher noch nicht. Ich werde das Mal ausprobieren.(cool)

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

16.10.2018, 22:46:58 via Website

Hallo,
ich habe jetzt ein bisschen herumprobiert. Als Test habe ich ein Kreuz in meine App gezeichnet. Funktioniert auch gut. Das Problem ist aber, dass die App abstürzt, wenn ich die Activity starte. Wenn ich die Zeilen mit "//" in OnCreate() als Kommentar markiere, Funktioniert es, aber das Menu verschwindet. Was kann ich machen, dass ich meine Linien Zeichnen kann und das Menu zusehen ist?

Hier mein Code der Activity:

public class EstwActivity extends AppCompatActivity {

private static final String LOG_TAG = "EstwApp";

MyCanvas myCanvas;
private View estwV;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_estw);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    estwV = findViewById(R.id.EstwV);

    //FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    //fab.setOnClickListener(new View.OnClickListener() {
    //    @Override
    //    public void onClick(View view) {
    //        Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
    //                .setAction("Action", null).show();
    //    }
    //});

    myCanvas = new MyCanvas(this);
    myCanvas.setBackgroundColor(Color.BLACK);
    setContentView(myCanvas);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    MenuItem itemTrennen = menu.findItem(R.id.item_trennen);
    MenuItem itemVerbinden = menu.findItem(R.id.item_verbinden);

    if (globaleVariablen.getIs_connected() == true) {
        itemTrennen.setVisible(true);
        itemVerbinden.setVisible(false);
    } else {
        itemTrennen.setVisible(false);
        itemVerbinden.setVisible(true);
    }
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (R.id.item_verbinden == item.getItemId()) {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }

    if(R.id.item_trennen == item.getItemId()) {
        trennen();
    }
    return true;
}

public void trennen() {
    if (globaleVariablen.getIs_connected() && globaleVariablen.getStream_out() != null) {
        globaleVariablen.setIs_connected(false);
        Log.d(LOG_TAG, "Trennen: Beende Verbindung");
        try {
            globaleVariablen.getStream_out().flush();
            globaleVariablen.getSocket().close();
            Toast.makeText(this, "Getrennt!", Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            Log.e(LOG_TAG,
                    "Fehler beim beenden des Streams und schliessen des Sockets: "
                            + e.toString());
        }
    } else
        Log.d(LOG_TAG, "Trennen: Keine Verbindung zum beenden " + globaleVariablen.getIs_connected() + " " + globaleVariablen.getStream_out());
}





public class MyCanvas extends View {
    Paint paint = new Paint();

    private void init() {
        paint.setColor(Color.RED);
        paint.setStrokeWidth(7);
    }

    public MyCanvas(Context context) {
        super(context);
        init();
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), paint);
        canvas.drawLine(canvas.getWidth(), 0, 0, canvas.getHeight(), paint);
    }
}

}

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

17.10.2018, 07:13:36 via Website

Hallo
Das liegt daran das du durch das zweite „setContentView“ dein XML Layout überschreibst. Du schaltest es somit aus als hättest du es nicht geladen. Dadurch existieren auch alle in dem Layout vorhandene ID’s nicht mehr.
setContentView(myCanvas);
setContenView sollte in einer Activity nur ein mal benutz bereden.

Erstens solltest du deine Custem Viev Klasse nicht als Innere Klasse erstellen sondern in einer eigenen Datei.
Zweiten binde deine CustemView Kasse im XML layout ein somit hast du auch weiterhin alle gestalterische Möglichkeiten die dir XML bietet.
Es ist zwar auch möglich es in Java einzubinden finde ich aber Umständlich besonders für Anfänger.

http://www.vogella.com/tutorials/AndroidCustomViews/article.html
https://developer.android.com/guide/topics/ui/custom-components

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

17.10.2018, 18:32:08 via Website

Die Klasse "MyCanvas" habe ich jetzt in eine extra Datei verschoben. In der Activity habe ich alles von der "MyCanvas" Klassse entfernt. Jetzt habe ich die Klasse mit
<de.my.bluetoothestw.MyCanvas
android:id="@+id/myCanvas"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

in das xml layout eingebunden. das sieht jetzt so aus:
image
aber auf meinem Handy stürzt die App beim öffnen der Activity ab. Wenn ich das in der xml Datei nicht einbinde, funktioniert es. Was habe ich falsch gemacht, dass die Activity abstürtzt?

— geändert am 17.10.2018, 18:43:51

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

17.10.2018, 20:58:31 via Website

Hallo Hilfreich wäre unter anderem wenn du uns das xml Layout auch zeigen würdest .
Bitte die komplette Datei, und wie deine Custom View jetzt aussieht .
Wo blendest du denn das Bild ein?
Auch interesant ist wie du von der Activty auf deine View zugreifst wenn du das überhaupt schon tust.

— geändert am 17.10.2018, 21:18:07

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

17.10.2018, 21:51:01 via Website

Hallo
content_estw.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="keine Links auf externe Webseiten"
    xmlns:app="keine Links auf externe Webseiten"
    xmlns:tools="keine Links auf externe Webseiten"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/estw"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="de.my.bluetoothestw.EstwActivity"
    tools:showIn="@layout/activity_estw">

    <de.my.bluetoothestw.MyCanvas
        android:id="@+id/myCanvas"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>

activity_estw.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="keine Links auf externe Webseiten"
    xmlns:app="keine Links auf externe Webseiten"
    xmlns:tools="keine Links auf externe Webseiten"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="de.my.bluetoothestw.EstwActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?android:attr/textColorLink"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include
        layout="@layout/content_estw"
        android:layout_height="359dp" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

MyCanvas.java:

public class MyCanvas extends View {
    Paint paint = new Paint();

    private void init() {
        paint.setColor(Color.RED);
        paint.setStrokeWidth(7);
        paint.setAntiAlias(true);
    }

    public MyCanvas(Context context) {
        super(context);
        init();
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), paint);//canvas.height
        canvas.drawLine(canvas.getWidth(), 0, 0, canvas.getHeight(), paint);
    }
}

EstwActivity.java:

public class EstwActivity extends AppCompatActivity {

    private static final String LOG_TAG = "EstwApp";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_estw);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setSubtitle("@string/subtitle_activity_estw");

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem itemTrennen = menu.findItem(R.id.item_trennen);
        MenuItem itemVerbinden = menu.findItem(R.id.item_verbinden);

        if (globaleVariablen.getIs_connected() == true) {
            itemTrennen.setVisible(true);
            itemVerbinden.setVisible(false);
        } else {
            itemTrennen.setVisible(false);
            itemVerbinden.setVisible(true);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (R.id.item_verbinden == item.getItemId()) {
            Intent intent = new Intent(this, MainActivity.class);
            startActivity(intent);
        }

        if(R.id.item_trennen == item.getItemId()) {
            trennen();
        }
        return true;
    }
}

Das Bild ist nur als Hintergrund eingefügt.
Leider wird bei mir "Um Spam in unserem Forum zu vermeiden, können neue Mitglieder vorerst keine Links auf externe Webseiten veröffentlichen." angezeigt, somit musste ich an manchen stellen "keine Links auf externe Webseiten" schreiben.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

17.10.2018, 23:05:03 via Website

Hi
versuche mal

 android:layout_width="0dp"
 android:layout_height="0dp"
 app:srcCompat="?android:attr/panelBackground"
 android:id="@+id/imageView" app:layout_constraintEnd_toEndOf="parent"
 app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"
 app:layout_constraintStart_toStartOf="parent"/>

warum nur wrap_content ? du willst doch das gesamte Bild ausfüllen.
akerpukte sind auch nicht gesetzt.
und ein hindergrund Farbe oder Drawable ist auch nicht gesetz solte bei einer View babei sein.

in der View Klasse soltest du alle drei Kostrucktor verwenden.

public GameZoomView(Context context) {
 super(context);

}
/--------------------------------------------------------------------/
public GameZoomView(Context context, AttributeSet attrs) {
super(context, attrs);

}
/--------------------------------------------------------------------/
public GameZoomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

18.10.2018, 08:22:50 via Website

Hallo

Ich würde das etwas anders machen.
Ich würde nicht das Bild als Hindergrund anzeigen denn da wirst du auch wieder Verschiebungen bei unterschiedlichen Geräten Display Auflösungen bekommen.

Das Bild dein GleisLayout wurde ich als Bild in den Assets oder als Drawable mitgeben.
Welche Auflösung musst du entscheiden würde mich an der Display Auflösung orientieren.
In der grösse des Bildes erstellst du nein Bitmap.
Das Bild lädst du aus den assets in das Bitmap. Nun erstellst du ein Canvas aus dem Bitmap.
Jetst kannst du uber das Canvas aub das Bitmap zeichnen.
Wenn du ferig gezeichnet hast kannst du das Bitmap einem im XML Layut erstellten ImagView zum anzeigen Übergeben.
Das geht auch ohne das du eine Klasse ableiten musst..

http://germanylandofinnovation.com/questions/3582/erstellen-einer-leeren-bitmap-und-zeichnen-von-canvas-in-android.html

https://gist.github.com/alvareztech/6627673

https://individuapp.com/softwareentwicklung/android-kurs/assets-ressourcen-lokalisierung/
https://gist.github.com/alvareztech/6627673

— geändert am 18.10.2018, 09:03:52

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

18.10.2018, 10:14:52 via Website

Hallo nur mal zu Info man kann hier imForum nur eine Antwort zu besten machen. Wenn dir andere auch gefallen dann Kicke auf gefallen. Wenn du dich mit der besten umentscheidest dann musst du die alte erst zurücknemen.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

18.10.2018, 10:42:19 via Website

Ja. Ich bin ausversehen drauf gekommen.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

19.10.2018, 13:02:55 via Website

Hallo
Danke dir! Die App stürtzt nicht mehr ab. Wie kann ich jetzt z.B.: die Farbe der Linie zu einem späteren Zeitpunkt ändern und eine neue Linie zeichnen?

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

20.10.2018, 21:01:00 via Website

Hallo
Kann ich dann die Linie wieder Löschen oder muss ich eine neue drüber Zeichnen? Und wie geht das?

— geändert am 20.10.2018, 21:01:39

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

21.10.2018, 16:16:34 via Website

Nein Löschen kannst du das nicht. Das ist eine Pixelgrafik .
Entweder wieder drüberzeichen oder das Bild wieder neu laden.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

21.10.2018, 16:20:07 via Website

Wie funktioniert das genau. Ich habe bis jetzt nur in die onDraw() Methode drawLine() eingefügt. Funktioniert auch, aber wie kann ich jetzt, wenn etwas auf meiner Anlage passiert, eine neue Linie drüber Zeichnen?

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

21.10.2018, 16:31:27 via Website

Für jeden gleisabschnitt würde ich eine Variable erstellen in die aussagt ob das entsprechende stück Rot oder Grün oder transparent werden soll.
Für die gesamte Grafik Ausgabe würde ich eine Methode machen. Als erstes würde ich das Hintergrund Bild in das Bitmap und Cavas laden.
Danach die gleisabschnitte drüber zeichnen mit der Farbe in der dazugehörigen variablen . ist nur Transparent gesetzt wird an der stelle nur der Hintergrund erscheinen.
Diese Methode rufst du nun immer wieder auf wenn sich etwas geändert hat . die Grafik Ausgabe wird somit immer wieder von vorne neu gezeichnet.
Die variablen kannst du nun von deiner Programm Logik aus setze und immer wieder die Grafik Ausgabe neu zeichnen lassen.

Hilfreich?
PBahner
Kommentieren
PBahner
  • Forum-Beiträge: 40

21.10.2018, 16:46:54 via Website

Muss die Methode in die MyCanvas Klasse? Und kann ich diese von meiner EstwActivity.java starten?

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

21.10.2018, 17:20:47 via Website

Die Variablen erstellst du in der MyCanvas Klasse. Da solltest du alles was mit grafik zutuhen hat machen. Die Variablen kannst du entweder direkt selber setzen oder durch getter und setter Methoden.

In der Activity erzeugst du eine Instant von MyCanvas nun kannst du auf die variablen zugreifen.
Das neu Zeichen veranlasst du mit „inalidate() oder postInvalidate() „ auf die erstellte Instanz.
Damit wird die onDraw Methode neu aufgerufen und deine Grafik geupdatet.

Hilfreich?
PBahner
Kommentieren
PBahner
  • Forum-Beiträge: 40

21.10.2018, 19:11:09 via Website

OK das sollte gehen. Was soll ich aber in die Klammer schreiben?

MyCanvas MyCanvas = new MyCanvas (?)

— geändert am 21.10.2018, 19:11:31

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

21.10.2018, 19:21:01 via Website

Hatte dir ja schon gesagt das du alle drei konstrucktoren in der klasse erstellen sollst.
Und dann übergibst du den context this.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

21.10.2018, 19:24:48 via Website

Ich habe alle 3 erstellt. Wenn ich nur this reinschreibe, stürzt die App ab.

"Attempt to invoke virtual method ... on a null object reference"

— geändert am 21.10.2018, 19:33:30

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

21.10.2018, 19:43:52 via Website

Zeige mal wie du das machst.
Wo hast du diese Zeile MyCanvas MyCanvas = new MyCanvas (?)
die Variable kann nicht wie die Klasse heißen

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

21.10.2018, 19:46:32 via Website

Ich habe in die Estw Activity

MyCanvas canvas = new MyCanvas (this);

geschrieben und die App stürzt ab.

— geändert am 21.10.2018, 19:47:13

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

21.10.2018, 19:52:55 via Website

Wie sieht es denn in deiner Mycanvas aus ?
Wenn es ohne Instanz nicht abstürzt wird der Fehler wohl in der Klasse sein.

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

22.10.2018, 17:46:48 via Website

Hallo Jokel
die MyCanvas.java sieht jetzt so aus:

public class MyCanvas extends View {
    Paint paint = new Paint();
    boolean belegt = true;

    private void init() {
        paint.setColor(Color.RED);
        paint.setStrokeWidth(5);
        paint.setAntiAlias(true);
    }

    public MyCanvas(Context context) {
        super(context);
        init();
    }

    public MyCanvas(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyCanvas(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    @Override
    public void onDraw(Canvas canvas) {
        int mX = canvas.getWidth() / 120;
        int mY = canvas.getHeight() / 90;

        int posX_10 = 10 * mX;
        int posX_30 = 30 * mX;
        int posX_40 = 40 * mX;
        int posX_50 = 50 * mX;
        int posX_80 = 80 * mX;
        int posX_90 = 90 * mX;
        int posX_100 = 100 * mX;
        int posX_110 = 110 * mX;
        int posY_20 = 20 * mY;
        int posY_30 = 30 * mY;
        int posY_60 = 60 * mY;
        int posY_70 = 70 * mY;
        int posY_80 = 80 * mY;

        canvas.drawLine(posX_10, posY_80, posX_80, posY_80, paint);
        paint.setColor(Color.YELLOW);

        canvas.drawLine(posX_80, posY_80, posX_90, posY_70, paint);
        canvas.drawLine(posX_80, posY_70, posX_90, posY_70, paint);

        if (belegt) {
            paint.setColor(Color.RED);
        } else {
            paint.setColor(Color.YELLOW);
        }


        canvas.drawLine(posX_90, posY_70, posX_100, posY_70, paint);
        canvas.drawLine(posX_100, posY_70, posX_110, posY_60, paint);
        canvas.drawLine(posX_110, posY_60, posX_110, posY_30, paint);
        canvas.drawLine(posX_110, posY_30, posX_100, posY_20, paint);
        canvas.drawLine(posX_100, posY_20, posX_90, posY_20, paint);

        canvas.drawLine(posX_90, posY_20, posX_50, posY_20, paint);
        paint.setColor(Color.YELLOW);

        canvas.drawLine(posX_50, posY_20, posX_40, posY_20, paint);
        canvas.drawLine(posX_50, posY_30, posX_40, posY_20, paint);
        paint.setColor(Color.RED);

        canvas.drawLine(posX_40, posY_20, posX_30, posY_20, paint);
        paint.setColor(Color.YELLOW);


    }
}
Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

22.10.2018, 18:29:17 via Website

also erstmal das geht nicht im Klassenrumpf. Paint paint = new Paint();
kein Statement im KlassenRumpf

public class MyCanvas extends View {
Paint paint;
boolean belegt = true;

private void init() {
    paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStrokeWidth(5);
    paint.setAntiAlias(true);
}
Hilfreich?
PBahner
Kommentieren
PBahner
  • Forum-Beiträge: 40

22.10.2018, 18:34:45 via Website

Ok Danke!
Die App stürtzt aber trotzdem noch ab.

Fehlermeldung:

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{de.my.bluetoothestw/de.my.bluetoothestw.EstwActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference

— geändert am 22.10.2018, 18:36:01

Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

22.10.2018, 18:42:34 via App

Da stimmt was mit deinem Context für die Resoirces ist.
Schau mal in die angegebene Zeile oder poste den Code.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

22.10.2018, 18:46:23 via Website

public class EstwActivity extends AppCompatActivity {

    private static final String LOG_TAG = "EstwApp";
    MyCanvas canvas = new MyCanvas(this); // hier stürtzt die App anscheinend ab

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_estw);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setSubtitle("MoBa Steuerung");

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem itemTrennen = menu.findItem(R.id.item_trennen);
        MenuItem itemVerbinden = menu.findItem(R.id.item_verbinden);

        if (globaleVariablen.getIs_connected() == true) {
            itemTrennen.setVisible(true);
            itemVerbinden.setVisible(false);
        } else {
            itemTrennen.setVisible(false);
            itemVerbinden.setVisible(true);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (R.id.item_verbinden == item.getItemId()) {
            Intent intent = new Intent(this, MainActivity.class);
            startActivity(intent);
        }

        if(R.id.item_trennen == item.getItemId()) {
            trennen();
        }

        if(R.id.item_btn == item.getItemId()) {
            TextView t = (TextView) findViewById(R.id.textView);
            t.setText("gedrueckt");
            canvas.belegt = false;
            canvas.invalidate();
        }
        return true;
    }
Hilfreich?
Kommentieren
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

22.10.2018, 18:49:05 via App

Richtig, bei der Markierten Zeile stürtzt es ab, da die Activity noch nicht instantiiert ist.
Du kannst den Canvas erst in der OnCreate passend instantiieren.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
PBahner
Kommentieren
PBahner
  • Forum-Beiträge: 40

22.10.2018, 19:20:47 via Website

Vielen Dank!(cool)
Die App stürtzt nicht mehr ab, aber wenn ich jetzt in der EstwActivity.java canvas.invalidate(); aufrufe, passiert überhaupt nichts

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

22.10.2018, 20:13:28 via Website

dann teste mal postInvalidate() hatte ich dir auch schon gesagt.

Das du keine Fuktionsaufrufe im Klassenrumpf machen kannst hatte ich dir auch schon in der Canvas Klasse gesagt.

Was soll denn eigentlich passieren? hast du den auch etwas verändert damit du in der Anzeige auch was siehst.
Woher willst du wissen das die ondraw nicht aufgerufen wird? Hast du das mit dem Debugger getestet?

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

22.10.2018, 20:31:57 via Website

Hallo
postInvalidate() hat ebenso nicht Funktioniert. Ich habe mir im Menü ein Item eingebaut. Wenn ich darauf Drücke wird "belegt" auf false gesetzt (siehe Code). Im Debugger hat es auch nichts angezeigt.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

23.10.2018, 06:00:53 via Website

Hi also ich würde behaupten das du zwei verschiedene instanzen hast. Denn beim Aufbau der Grafik wird auch schon eine Instanz erstellt.
Deine Instanz die du im Code erzeugt ist dann eine andere. Das setzen der Variablen und neuzeichnen machst du somit auf der Instanz die nicht angezeigt wird.

— geändert am 23.10.2018, 10:27:24

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

23.10.2018, 08:53:42 via Website

versuche es mal so, hiermit solltest du die Instanz der view bekommen.

public class MyCanvas extends View {
Paint pain;
boolean belegt = true;

private void init() {
    paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStrokeWidth(5);
    paint.setAntiAlias(true);
}

public MyCanvas(Context context) {
    this(context, null, 0);

}

public MyCanvas(Context context, AttributeSet attrs) {
    this(context, attrs, 0);

}

public MyCanvas(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
}

//----------------------------------------------------------------------

public class EstwActivity extends AppCompatActivity {

private static final String LOG_TAG = "EstwApp";
MyCanvas canvas;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_estw);

 canvas = (MyCanvas) findViewById (R.id.myCanvas);
 canvas.belegt = false;
 canvas.postpostInvalidate();

— geändert am 23.10.2018, 08:57:39

Hilfreich?
PBahner
Kommentieren
PBahner
  • Forum-Beiträge: 40

23.10.2018, 14:33:41 via Website

Vielen Dank!
So hat alles Funktioniert, wie es soll.(cool)

Hilfreich?
Kommentieren
PBahner
  • Forum-Beiträge: 40

07.11.2018, 18:50:20 via Website

Eine Frage habe ich nun noch.
Warum kann ich in die OnDraw() Methode keine eigene Methode schreiben wie z.B.:

private void GleisText(int x, int y) {
        paint.setTextSize(m*4);
        paint.setColor(Color.BLACK);
        paint.getFontMetrics(fm);
        int margin = 5;

        canvas.drawRect(pos("x", x) - margin, pos("y", y) + fm.top - margin,
                pos("x", x) + paint.measureText("1") + margin, pos("y", y) + fm.bottom
                        + margin, paint);


        paint.setColor(Color.WHITE);
        canvas.drawText("1", pos("x", x), pos("y", y), paint);
    }

Wenn ich es außerhalb der Methode einsetzte, wird canvas Rot. Wie kann ich das Lösen? Ich möchte das nicht für jedes Gleis neu einsetzen.

Hilfreich?
Kommentieren
Jokel
  • Forum-Beiträge: 1.530

07.11.2018, 18:57:50 via Website

Da musst du das canvas was du in der ondraw Methode bekommst auch an deine Methode mit geben. So wie dein x und y.

— geändert am 07.11.2018, 19:04:44

Hilfreich?
PBahner
Kommentieren
PBahner
  • Forum-Beiträge: 40

07.11.2018, 19:02:25 via Website

Danke! hat Funktioniert.(cool)

Hilfreich?
Kommentieren